android实现自定义seekbar,重新绘制background、secondaryProgress、progress进度条、滑块thumb

原生的seekbar,设置progressDrawable可以改变seekbar进度条的样式,例如如下样式。



    
        
            
            
        
    

    
        
            
                
                
            
        
    

    
        
            
                
                
            
        
    

原生效果图:
在这里插入图片描述
原生的seekbar在4.4系统控件的高度就是seekbar的高度,而且maxHeight属性不起作用。还有就是如果设置渐变色,渐变色是从0到最大进度渐变,如果想使渐变色从0到当前进度渐变而颜色透明度是从0-255,那原生的就满足不了了。如图
android实现自定义seekbar,重新绘制background、secondaryProgress、progress进度条、滑块thumb_第1张图片
下面介绍下如何重新绘制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的位置。

android实现自定义seekbar,重新绘制background、secondaryProgress、progress进度条、滑块thumb_第2张图片

你可能感兴趣的:(android,自定义seekbar,自定义)