1、应用场景
SeekBar常用于可提供用户交互的进度选择或刻度选择中,如视频播放的拖动条、各种灵敏度设置等。
2、用法
与其他控件用法相同,创建或者xml定义
SeekBar是ProgressBar的子类,多出来的就是Thumb部分,也就是用户可拖动的Drawable。监听OnSeekBarChangeListener判断用户动作。
android:max="100" //最大刻度
android:progress="50" //当前刻度
android:progressDrawable="@drawable/**" //背景图形
android:thumb="@drawable/**"//游标图形
此处考虑切片容易拉伸变形,建议使用自定义的shape,progressDrawable的定义可以看android内置shape,此处不再列出。
3、注意事项
3.1 高度问题
在自定义SeekBar时,经常会遇到后面的进度条高度被拉伸的问题,如下图所示:
这时可以通过设置minHeight和maxHeight解决。
android:minHeight="3dp"
android:maxHeight="3dp"
因为Seekbar的进度条的高度会受到这两个属性限制。这里不能用height属性,否则效果就是这样的:(height=3dp)
可以看到,自定义的进度条被隐藏了,Thumb也显示不全。
这种方案其实不是很好用,因为在某些机器上,如果不配合图形的Bound,这个值稍微大点,就会回到原效果,建议动态设置Drawable时都设好Bound。
3.2 Thumb无法显示全的问题
超出屏幕边界,这时候需要设置paddingLeft和paddingRight属性来限制背景的宽度。
3.3 android 2.X系统不显示seekbar
具体表现是进去的时候seekbar展示,因为第一次进去进度条是xml定义的,第二次调用setThumb和setProgressDrawable也没问题,但是第三次调用这两个接口时,进度条消失,如下:
按道理应该显示进度条的Thumb和刻度,但是却没有显示。这是由于SeekBar中动态设置图形时,setProgressDrawable、setThumb设置的Drawable在2.X系统丢失了边界信息导致的。
我们要从原Drawable中获取Bound信息,然后赋值到新Drawable内:
背景图片:
Rect bounds =mSeekBar.getProgressDrawable().getBounds();
mSeekBar.setProgressDrawable(diableDrawable);
mSeekBar.getProgressDrawable().setBounds(bounds);
Thumb图片:
if(null != mSeekBar.getSeekBarThumb()) {
Rect thumbDrawableBounds = mSeekBar.getSeekBarThumb().getBounds();
mSeekBar.setThumb(getResources().getDrawable(R.drawable.ic_slider_point_disable));
mSeekBar.getSeekBarThumb().setBounds(thumbDrawableBounds);
}
这里还有个坑:SeekBar setThumb是支持到2.3的,但是getThumb是不支持2.3的,我们需要重写SeekBar的setThumb方法并把Drawable保存起来,提供getSeekBarThumb接口访问,直接使用getThumb在低版本会崩溃。
3.4 游标位置监听
存在两种办法,第一种是笨办法,通过当前返回的刻度比例计算刻度的距左margin值,第二种是读取Thumb的Drawable的绘制区域来设置距左margin值。
3.4.1 笨办法:
private int getMarginLeftBySensitivity(int sensitivity) {
double ratio = sensitivity/100.0;
double parentWidth = Environment.getScreenWidth(this) - UIUtil.dip2px(this, 16) * 2;
double selfWidth = UIUtil.dip2px(this, 30);
int margin = (int)(ratio * parentWidth - selfWidth /2.0);
return margin;
}
其实就是计算标尺在整个标尺长度中的距左间距。
3.4.2 取Thumb绘制区域法
protected void positionThumbLabel(XSeekBar seekBar, TextView label)
{
Rect tr = seekBar.getSeekBarThumb().getBounds();
label.setWidth(tr.width());
LayoutParams param = (LayoutParams) label.getLayoutParams();
param.leftMargin = tr.left;
label.setLayoutParams(param);
}