原生的seekbar,设置progressDrawable可以改变seekbar进度条的样式,例如如下样式。
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="5dp" />
<solid android:color="#16dda9" />
</shape>
</item>
<item android:id="@android:id/secondaryProgress">
<clip>
<shape>
<corners android:radius="5dp" />
<solid android:color="#ae734a" />
</shape>
</clip>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="5dp" />
<gradient
android:type="linear"
android:angle="0"
android:startColor="#0cffff00"
android:endColor="#FFffff00"
/>
</shape>
</clip>
</item>
</layer-list>
原生效果图:
原生的seekbar在4.4系统控件的高度就是seekbar的高度,而且maxHeight属性不起作用。还有就是如果设置渐变色,渐变色是从0到最大进度渐变,如果想使渐变色从0到当前进度渐变而颜色透明度是从0-255,那原生的就满足不了了。如图
下面介绍下如何重新绘制seekbar的background、secondaryProgress、progress进度条、滑块thumb。
首先我们继承原生的Seekbar,方便用它自带的属性和方法。
第一步:实现onDraw方法,注释掉super.onDraw屏蔽掉原生的seekbar绘制。
1.)绘制seebar的background。background是静态的。
当没有设置背景图片的时候,我们会画一个宽高为new RectF(tDWidth/2, height/2-bacProgressHeight/2, width-tDWidth/2, height/2+bacProgressHeight/2)这样的矩形, path.addRoundRect是画一个圆角矩形,radiusArray是圆角数组。当有背景图片的时候,我们会把图片作为background的背景。
// background
canvas.save();
path.addRoundRect(new RectF(tDWidth/2, height/2-bacProgressHeight/2, width-tDWidth/2, height/2+bacProgressHeight/2), radiusArray, Path.Direction.CW);
if(bacProgressDrawable==null){
canvas.drawPath(path,paint);
}else{
canvas.clipPath(path);
bacProgressDrawable.setBounds(tDWidth/2, height/2-bacProgressHeight/2, width-tDWidth/2, height/2+bacProgressHeight/2);
bacProgressDrawable.draw(canvas);
}
canvas.restore();
2.)绘制seebar的secondaryProgress
当设置了secondaryProgress的值大于0的时候根据滑块的位置动态绘制它的矩形区域。
//secondprogress
if(secondProgress>0){
canvas.save();
secondeProgressPath.addRoundRect(new RectF(tDWidth/2, height/2-bacProgressHeight/2, secondProgress+tDHeight/2, height/2+bacProgressHeight/2), radiusArray, Path.Direction.CW);
if(secondeBacProgressDrawable==null){
canvas.drawPath(secondeProgressPath,secondePaint);
}else{
canvas.clipPath(secondeProgressPath);
secondeBacProgressDrawable.setBounds(tDWidth/2, height/2-bacProgressHeight/2, secondProgress+tDHeight/2, height/2+bacProgressHeight/2);
secondeBacProgressDrawable.draw(canvas);
}
canvas.restore();
}
设置了secondaryProgress属性后会调用setSecondaryProgress,刷新secondaryProgress进度。
@Override
public synchronized void setSecondaryProgress(int secondaryProgress) {
maxProgress = getMax()==0 ? 100 : getMax();
if(maxProgress==0||secondaryProgress>maxProgress||secondaryProgress<=0){
return;
}
final int myprogress = secondaryProgress+1;
observer = this.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
seekBar.getViewTreeObserver().removeGlobalOnLayoutListener(this);
width = seekBar.getMeasuredWidth();
secondProgress = ((width-tDWidth)*myprogress)/maxProgress;
//Log.e("secondProgress","secondProgress:"+secondProgress);
invalidate();
}
});
}
3.)绘制seebar的progress,随着滑块的移动动态改变progress区域。
//gradientprogress
canvas.save();
progressPath.reset();
progressRectF.set(tDWidth/2, height/2-bacProgressHeight/2, thumbScrollX+tDHeight/2, height/2+bacProgressHeight/2);
progressPath.addRoundRect(progressRectF, radiusArrayProgress, Path.Direction.CW);
if(progressDrawable!=null){
canvas.clipPath(progressPath);
progressDrawable.setBounds(tDWidth/2, height/2-bacProgressHeight/2, thumbScrollX+tDHeight/2, height/2+bacProgressHeight/2);
progressDrawable.draw(canvas);
}else{
LinearGradient mLinearGradient = new LinearGradient(0,0,thumbScrollX,0,colors,null, Shader.TileMode.CLAMP);
paintProgress.setShader(mLinearGradient);
canvas.drawPath(progressPath,paintProgress);
}
canvas.restore();
4.)绘制seebar的thumb滑块
//thumb
thumbDrawable.setBounds(0+thumbScrollX, height/2-tDHeight/2, tDWidth+thumbScrollX, height/2+tDHeight/2);
thumbDrawable.draw(canvas);
完整的onDraw逻辑
@Override
protected synchronized void onDraw(Canvas canvas) {
// background
canvas.save();
path.addRoundRect(new RectF(tDWidth/2, height/2-bacProgressHeight/2, width-tDWidth/2, height/2+bacProgressHeight/2), radiusArray, Path.Direction.CW);
if(bacProgressDrawable==null){
canvas.drawPath(path,paint);
}else{
canvas.clipPath(path);
bacProgressDrawable.setBounds(tDWidth/2, height/2-bacProgressHeight/2, width-tDWidth/2, height/2+bacProgressHeight/2);
bacProgressDrawable.draw(canvas);
}
canvas.restore();
//secondprogress
if(secondProgress>0){
canvas.save();
secondeProgressPath.addRoundRect(new RectF(tDWidth/2, height/2-bacProgressHeight/2, secondProgress+tDHeight/2, height/2+bacProgressHeight/2), radiusArray, Path.Direction.CW);
if(secondeBacProgressDrawable==n