美文网首页
圆角矩形ProgressBar小记

圆角矩形ProgressBar小记

作者: InKenKa | 来源:发表于2017-11-08 20:48 被阅读199次

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

    普通的一直圆形转的ProgressBar

    <style name="Widget.ProgressBar">
        <item name="indeterminateOnly">true</item>
        <item name="indeterminateDrawable">@drawable/progress_medium_white</item>
        <item name="indeterminateBehavior">repeat</item>
        <item name="indeterminateDuration">3500</item>
        <item name="minWidth">48dip</item>
        <item name="maxWidth">48dip</item>
        <item name="minHeight">48dip</item>
        <item name="maxHeight">48dip</item>
        <item name="mirrorForRtl">false</item>
    </style> 
    

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

    水平的ProgressBar

    <style name="Widget.ProgressBar.Horizontal">
        <item name="indeterminateOnly">false</item>
        <item name="progressDrawable">@drawable/progress_horizontal</item>
        <item name="indeterminateDrawable">@drawable/progress_indeterminate_horizontal</item>
        <item name="minHeight">20dip</item>
        <item name="maxHeight">20dip</item>
        <item name="mirrorForRtl">true</item>
    </style>
    

    @drawable/progress_indeterminate_horizontal:是一个帧动画

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

    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:id="@android:id/background">
            <shape>
                <corners android:radius="5dip" />
                <gradient
                    .....................
                />
            </shape>
        </item>
    ....................
    <item android:id="@android:id/progress">
            <clip>
                <shape>
                    <corners android:radius="5dip" />
                    <gradient
                        .....................
                    />
                </shape>
            </clip>
        </item>
    </layer-list>
    

    小结:
    一直旋转的系统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小记

          本文链接:https://www.haomeiwen.com/subject/tfxumxtx.html