原生的seekbar,设置progressDrawable可以改变seekbar进度条的样式,例如如下样式。
-
-
-
原生效果图:
原生的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==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();
}
//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();
//thumb
thumbDrawable.setBounds(0+thumbScrollX, height/2-tDHeight/2, tDWidth+thumbScrollX, height/2+tDHeight/2);
thumbDrawable.draw(canvas);
}
thumbScrollX是我们滑块x轴移动的距离,我们就是根据thumbScrollX的大小来控制seekbar的相关进度的。
第二步:让thumb滑动
1.)先得到thumbDrawable,实现setThumb方法。如何没有设置,会使用系统的自带的thumb。
@Override
public void setThumb(Drawable thumb) {
thumbDrawable = thumb;
tDWidth = thumbDrawable.getMinimumWidth();
tDHeight = thumbDrawable.getMinimumHeight();
}
2.)实现onTouchEvent方法,让thumb随x轴方向手势移动。计算出水平滑动的距离,刷新onDraw来改变滑块的x轴方向的位置。
@Override
public boolean onTouchEvent(final MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
thumbScrollX = (int) (downX-tDWidth/2);
if(thumbScrollX<=0){
thumbScrollX =0;
}else if(thumbScrollX>=(width-tDWidth)) {
thumbScrollX = width - tDWidth;
}
mOnSeekBarChangeListener.onStartTrackingTouch(seekBar);
invalidateDrawable(thumbDrawable);
calculateProgress(thumbScrollX);
break;
case MotionEvent.ACTION_MOVE:
float scrollX = event.getX()-downX;
float scrollY = event.getY()-downY;
downX = event.getX();
downY = event.getY();
if(Math.abs(scrollX)>Math.abs(scrollY)){//x轴y轴滑动方向
if(Math.abs(scrollY)=(width-tDWidth)&&thumbOffset==0x23456){
thumbScrollX = width-tDWidth;
}else if(thumbOffset!=0x23456){
if(thumbScrollX<=-thumbOffset){
thumbScrollX = -thumbOffset;
}else if(thumbScrollX>=(width-tDWidth+thumbOffset)){
thumbScrollX = width-tDWidth+thumbOffset;
}
}
invalidateDrawable(thumbDrawable);
calculateProgress(thumbScrollX);
mOnSeekBarChangeListener.onProgressChanged(seekBar,getProgress(),true);
}
}
break;
case MotionEvent.ACTION_UP:
calculateProgress(thumbScrollX);
mOnSeekBarChangeListener.onProgressChanged(seekBar,getProgress(),true);
mOnSeekBarChangeListener.onStopTrackingTouch(seekBar);
break;
}
return super.onTouchEvent(event);
}
public void calculateProgress(int thumbScrollX){
//计算进度
currentProgress = (thumbScrollX*maxProgress)/(width-tDWidth);
if(lastProgress!=currentProgress){
getProgress();
Log.e("currentProgress","currentProgress:"+currentProgress);
}
lastProgress = currentProgress;
}
第三部:实现setProgressDrawable方法,对bacProgressDrawable,secondeBacProgressDrawable,progressDrawable赋值。当设置了progressDrawable样式之后,解析LayerDrawable 拿到对应的ClipDrawable。如果没设置,会使用系统的默认drawable。
@Override
public void setProgressDrawable(Drawable d) {
if(d instanceof LayerDrawable){
LayerDrawable ld = (LayerDrawable)d;
Drawable drawable = ld.findDrawableByLayerId(android.R.id.background);
if(drawable!=null){
bacProgressDrawable = drawable;
}
ClipDrawable clipDrawableSeconde = (ClipDrawable)ld.findDrawableByLayerId(android.R.id.secondaryProgress);
if(clipDrawableSeconde!=null){
secondeBacProgressDrawable = clipDrawableSeconde;
clipDrawableSeconde.setLevel(10000);
}
ClipDrawable clipDrawableProgress = (ClipDrawable)ld.findDrawableByLayerId(android.R.id.progress);
if(clipDrawableProgress!=null){
progressDrawable = clipDrawableProgress;
//不设置 不显示
clipDrawableProgress.setLevel(10000);
}
}else{
bacProgressDrawable= d;
secondeBacProgressDrawable = d;
progressDrawable = d;
}
}
实现原生的setProgress,setSecondaryProgress方法并重改里边的逻达到和原生一样的效果。
@Override
public synchronized void setProgress(int progress) {
maxProgress = getMax()==0 ? 100 : getMax();
currentProgress = progress;
if(maxProgress==0||progress>maxProgress){
return;
}
final int myprogress = progress+1;
observer = this.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
seekBar.getViewTreeObserver().removeGlobalOnLayoutListener(this);
width = seekBar.getMeasuredWidth();
thumbScrollX = ((width-tDWidth)*myprogress)/maxProgress;
calculateProgress(thumbScrollX);
invalidateDrawable(thumbDrawable);
}
});
}
@Override
public synchronized void setSecondaryProgress(int secondaryProgress) {
maxProgress = getMax()==0 ? 100 : getMax();
if(maxProgress==0||secondProgress>maxProgress||secondProgress<=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();
}
});
}
/**
* 覆盖掉原生的监听事件,用原生的监听实现自己的逻辑
*/
private SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
@Override
public void setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener l) {
mOnSeekBarChangeListener = l;
}
完整代码:
package com.yq.wtwidgetdemo.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewTreeObserver;
import android.widget.SeekBar;
import com.yq.wtwidgetdemo.R;
/**
* Created by lenovo on 2019/6/3.
*/
public class SelfSeekBarView extends SeekBar{
private SelfSeekBarView seekBar;
private ViewTreeObserver observer;
private int tDWidth,tDHeight;//thumb 宽高
private Paint paint,paintProgress,secondePaint;//背景,进度,第二进度画笔
private Path path,progressPath,secondeProgressPath;//背景,进度,第二进度路径
private Drawable thumbDrawable,bacProgressDrawable,secondeBacProgressDrawable,progressDrawable;//thumb,背景,第二进度 当前进度 图片
private int thumbScrollX = 0;//thumbu在x州滚动距离
private int width,height;//seekbar宽高
private float roundRadius = 20.0f; //进度条圆角半径
private float[] radiusArray,radiusArrayProgress;//进度条圆角数组
private int bacProgressWidth,bacProgressHeight;//进度条宽高
private RectF progressRectF = new RectF();
private String bacProgressColor = "#ff00ff";//默认背景条颜色
private String secondeBacProgressColor = "#00ffff";//默认第二进度条颜色
private int secondProgress = 0;//默认第二进度进度条进度
private boolean isHasSecondeProgress = false;//是否设置了第二进度条
private int thumbOffset = 0x23456;//thumbOffset默认值
private float downX,downY;
private float minOffsetY = 20;//y轴最小滑动范围
private float scrollOffset = 0.9f;//x轴滑动阻尼系数
private int maxProgress = 100;
private int currentProgress = 0;
private int lastProgress = 0;
private int minHeight;
private int maxHeight;
private int[] colors = new int[]{Color.parseColor("#19ffff00"),Color.parseColor("#66ffff00"),Color.parseColor("#BFffff00"),Color.parseColor("#FFffff00")};
public SelfSeekBarView(Context context) {
super(context);
init(null);
}
public SelfSeekBarView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public SelfSeekBarView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
public void init(AttributeSet attrs){
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.SeekbarView);
maxHeight = typedArray.getDimensionPixelSize(R.styleable.SeekbarView_android_maxHeight,0);
roundRadius = typedArray.getDimension(R.styleable.SeekbarView_roundRadius,0);
tDWidth = typedArray.getDimensionPixelSize(R.styleable.SeekbarView_thumbWidth,0);
tDHeight = typedArray.getDimensionPixelSize(R.styleable.SeekbarView_thumbHeight,0);
typedArray.recycle();
tDWidth = tDWidth==0 ?thumbDrawable.getMinimumWidth() : tDWidth;
tDHeight = tDHeight ==0 ?thumbDrawable.getMinimumHeight() :tDHeight;
seekBar = this;
observer = this.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
seekBar.getViewTreeObserver().removeGlobalOnLayoutListener(this);
width = seekBar.getMeasuredWidth();
height = seekBar.getMeasuredHeight();
}
});
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.parseColor(bacProgressColor));
secondePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
secondePaint.setColor(Color.parseColor(secondeBacProgressColor));
paintProgress = new Paint(Paint.ANTI_ALIAS_FLAG);
path = new Path();
progressPath = new Path();
secondeProgressPath = new Path();
radiusArray = new float[]{roundRadius, roundRadius, roundRadius, roundRadius, roundRadius, roundRadius, roundRadius, roundRadius};
//leftTop,leftTop;rightTop;rightTop;rightBottom;rightBottom;leftBottom;leftBottom;
radiusArrayProgress = new float[]{roundRadius, roundRadius, 0, 0, 0, 0, roundRadius, roundRadius};
//背景图片和第二进度图片
//bacground drawable
//bacProgressDrawable = getResources().getDrawable(R.drawable.seek_bac_icon);
//secondebacground drawable
//secondeBacProgressDrawable = getResources().getDrawable(R.drawable.seek_seconde_bac);
//progress drawable
//progressDrawable = getResources().getDrawable(R.drawable.seek_secondebac_icon);
//对thumbOffset进行判断
/*thumbOffset = 100;
if(thumbOffset>0){
thumbOffset = 0x23456;
}
if(thumbOffset>width/2){
thumbOffset = width/2;
}*/
minHeight = getMinimumHeight();
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
bacProgressWidth = tDWidth/2;
bacProgressHeight = maxHeight==0 ? tDHeight/2 : maxHeight;
int width = getMeasuredWidth()height){
bacProgressHeight = height;
}
setMeasuredDimension(width,height);
}
@Override
public void setMinimumHeight(int minHeight) {
this.minHeight = minHeight;
super.setMinimumHeight(minHeight);
}
@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==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();
}
//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();
//thumb
thumbDrawable.setBounds(0+thumbScrollX, height/2-tDHeight/2, tDWidth+thumbScrollX, height/2+tDHeight/2);
thumbDrawable.draw(canvas);
}
@Override
public synchronized void setProgress(int progress) {
maxProgress = getMax()==0 ? 100 : getMax();
currentProgress = progress;
if(maxProgress==0||progress>maxProgress){
return;
}
final int myprogress = progress+1;
observer = this.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
seekBar.getViewTreeObserver().removeGlobalOnLayoutListener(this);
width = seekBar.getMeasuredWidth();
thumbScrollX = ((width-tDWidth)*myprogress)/maxProgress;
invalidateDrawable(thumbDrawable);
calculateProgress(thumbScrollX);
}
});
}
@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();
}
});
}
@Override
public synchronized int getProgress() {
return this.currentProgress;
}
@Override
public void setThumbOffset(int thumbOffset) {
}
@Override
public void setThumb(Drawable thumb) {
thumbDrawable = thumb;
}
@Override
public void setProgressDrawable(Drawable d) {
if(d instanceof LayerDrawable){
LayerDrawable ld = (LayerDrawable)d;
Drawable drawable = ld.findDrawableByLayerId(android.R.id.background);
if(drawable!=null){
bacProgressDrawable = drawable;
}
ClipDrawable clipDrawableSeconde = (ClipDrawable)ld.findDrawableByLayerId(android.R.id.secondaryProgress);
if(clipDrawableSeconde!=null){
secondeBacProgressDrawable = clipDrawableSeconde;
clipDrawableSeconde.setLevel(10000);
}
ClipDrawable clipDrawableProgress = (ClipDrawable)ld.findDrawableByLayerId(android.R.id.progress);
if(clipDrawableProgress!=null){
progressDrawable = clipDrawableProgress;
//不设置 不显示
clipDrawableProgress.setLevel(10000);
}
}else{
bacProgressDrawable= d;
secondeBacProgressDrawable = d;
progressDrawable = d;
}
}
@Override
public boolean onTouchEvent(final MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
thumbScrollX = (int) (downX-tDWidth/2);
if(thumbScrollX<=0){
thumbScrollX =0;
}else if(thumbScrollX>=(width-tDWidth)) {
thumbScrollX = width - tDWidth;
}
mOnSeekBarChangeListener.onStartTrackingTouch(seekBar);
invalidateDrawable(thumbDrawable);
calculateProgress(thumbScrollX);
break;
case MotionEvent.ACTION_MOVE:
float scrollX = event.getX()-downX;
float scrollY = event.getY()-downY;
downX = event.getX();
downY = event.getY();
if(Math.abs(scrollX)>Math.abs(scrollY)){//x轴y轴滑动方向
if(Math.abs(scrollY)=(width-tDWidth)&&thumbOffset==0x23456){
thumbScrollX = width-tDWidth;
}else if(thumbOffset!=0x23456){
if(thumbScrollX<=-thumbOffset){
thumbScrollX = -thumbOffset;
}else if(thumbScrollX>=(width-tDWidth+thumbOffset)){
thumbScrollX = width-tDWidth+thumbOffset;
}
}
invalidateDrawable(thumbDrawable);
calculateProgress(thumbScrollX);
mOnSeekBarChangeListener.onProgressChanged(seekBar,getProgress(),true);
}
}
break;
case MotionEvent.ACTION_UP:
calculateProgress(thumbScrollX);
mOnSeekBarChangeListener.onProgressChanged(seekBar,getProgress(),true);
mOnSeekBarChangeListener.onStopTrackingTouch(seekBar);
break;
}
return super.onTouchEvent(event);
}
/**
* 覆盖掉原生的监听事件,用原生的监听实现自己的逻辑
*/
private SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener = new SelfSeekBarView.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
@Override
public void setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener l) {
mOnSeekBarChangeListener = l;
}
public void calculateProgress(int thumbScrollX){
//计算进度
currentProgress = (thumbScrollX*maxProgress)/(width-tDWidth);
if(lastProgress!=currentProgress){
getProgress();
Log.e("currentProgress","currentProgress:"+currentProgress);
}
lastProgress = currentProgress;
}
}
xml:
drawable:seekbar_layerlist.xml
-
-
-
thumb:seekbar_thumb_shape
自定义属性:attrs
总结:计算手指x轴移动的距离刷新onDraw方法,在onDraw里动态改变secondaryProgress和progress的宽度实现进度样式的变化。同时改变滑块thumb的位置。