圆角矩形ProgressBar小记

1.系统ProgressBar样式实现原理分析

普通的一直圆形转的ProgressBar

 

上面的“@drawable/progress_medium_white” 是一个帧动画

水平的ProgressBar


@drawable/progress_indeterminate_horizontal:是一个帧动画

@drawable/progress_horizontal:是一个LayerDrawable,主要由一个表示底色的Drawable,和表示Progress的ClipDrawable组成


    
        
            
            
        
    
....................

        
            
                
                
            
        
    

小结:
一直旋转的系统ProgressBar,其实只是一直播放的帧动画
水平的ProgressBar,是由于ClipDrawable根据Progress,从而改变ClipDrawable的Level


2.方案选择

  1. 参考系统水平ProgressBar的样式实现,自定义特殊的Drawable,传入ProgressBar(由于是系统实现,优先考虑)
  2. 继承ProgressBar,重写里面的Draw方法

3.方案一

  1. 自定义一个Drawable,重写里面的Draw方法,绘制一个圆角矩形作为底色
  2. 再自定义一个Drawable,重写里面的Draw方法,根据Level值,绘制一个当前的进度
  3. 通过LayerDrawable把这两个Drawable层叠起来,得到最后的LayerDrawable
  4. 调用ProgressBar的setProgressDrawable,设置该LayerDrawable

结果:失败。通过代码调用ProgressBar的setProgressDrawable发现调用无效,不解。


4.方案二

  1. 生成一个矩形:RectF rectF = new RectF(mPathWidth,mPathWidth,getWidth()-mPathWidth,getHeight()-mPathWidth);
    注意:因为是只要边框,所以生成的矩形要减去边框的宽度
  2. 生成圆角矩形的Path
  3. 利用PathMeasure,获取Path的某一部分,并绘制到Canvas

具体代码:https://github.com/yinfork/Android-Dev-Demos/blob/master/app/src/main/java/com/inkenka/devdemos/processbar/RoundCornerProgressBar.java

public class RoundCornerProgressBar extends ProgressBar {
    private Paint mBackgroundPaint = new Paint();
    private Paint mProgressPaint = new Paint();
    private float mRadius;
    private int mPathWidth;
    private float mStartOffsetPercent;

构造函数(略)
 
    @Override
    public void onDraw(Canvas canvas) {
        drawBackground(canvas);
        drawProgress(canvas);
    }

    private void drawBackground(Canvas canvas){
        RectF rectF = new RectF(mPathWidth,mPathWidth,getWidth()-mPathWidth,getHeight()-mPathWidth);
        canvas.drawRoundRect(rectF, mRadius, mRadius, mBackgroundPaint);
    }

    private void drawProgress(Canvas canvas){
        RectF rectF = new RectF(mPathWidth,mPathWidth,getWidth()-mPathWidth,getHeight()-mPathWidth);
        Path path = new Path();

        path.addRoundRect(rectF, mRadius, mRadius, Path.Direction.CW);

        Path mRenderPaths = new Path();
        PathMeasure mPathMeasure = new PathMeasure(path, false);

        float pathOffset = mPathMeasure.getLength() * (getProgress()/100f);
        float startOffset = mPathMeasure.getLength() * mStartOffsetPercent;

        if(pathOffset + startOffset < mPathMeasure.getLength()){
            if (mPathMeasure.getSegment(startOffset, startOffset + pathOffset, mRenderPaths, true)) {
                canvas.drawPath(mRenderPaths, mProgressPaint);
            }
        } else {
            if (mPathMeasure.getSegment(startOffset, mPathMeasure.getLength(), mRenderPaths, true)) {
                canvas.drawPath(mRenderPaths, mProgressPaint);
            }
            if (mPathMeasure.getSegment(0, pathOffset + startOffset - mPathMeasure.getLength(), mRenderPaths, true)) {
                canvas.drawPath(mRenderPaths, mProgressPaint);
            }
        }
    }
}

你可能感兴趣的:(圆角矩形ProgressBar小记)