Android MaterialProgressDrawable类

一:常用方法

返回值方法和描述
voidupdateSizes(int size)
设置大小,可以选LARGE、DEFAULT
voidshowArrow(boolean show)
设置是否显示箭头
voidsetArrowScale(float scale)
设置箭头缩放大小,0f~1f
voidsetStartEndTrim(float startAngle, float endAngle)
设置进度条的开始和结尾,也就是长度,范围0f~1f,比如setStartEndTrim(0f,0.8f)
voidsetProgressRotation(float rotation)
设置旋转角度,0f~1f
voidsetBackgroundColor(int color)
设置背景颜色
voidsetColorSchemeColors(int… colors)
设置进度条的颜色,可以是多种颜色,转一圈换一个
voidsetAlpha(int alpha)
设置透明度,0-255,注意:默认一开始透明度是0
voidstart()
开始转圈动画
voidstop()
终止进行中的动画,并且将进度条长度归零
intgetAlpha()
获取当前透明度
intgetIntrinsicHeight()
获取Drawable高度
intgetIntrinsicWidth()
获取Drawable宽度

二:使用

从v4包复制MaterialProgressDrawable类,改为public class

初始化
    private final int CIRCLE_BG_LIGHT = 0xFFFAFAFA;//背景颜色十六进制值
    public void init() {
        //parent是mImageView的父布局,用于启动动画,不能为null
        mProgress = new MaterialProgressDrawable(this, parent);
        mProgress.setBackgroundColor(CIRCLE_BG_LIGHT);
        mProgress.setColorSchemeColors(colors);
        mImageView.setImageDrawable(mProgress);
    }

注意: setBackgroundColor和setColorSchemeColors设置的颜色值不能之间使用R.color.xx,可以使用颜色的十六进制,如0xFFFAFAFA,或者 getResources().getColor(R.color.xx)转换成十六进制

启动:
    mProgress.setAlpha(255);
    mProgress.setStartEndTrim(0f, 0.8f);
    mProgress.setArrowScale(1f); //0~1之间
    mProgress.setProgressRotation(1);
    mProgress.showArrow(true);
    mProgress.start();
停止
    mProgress.stop();

三:源码

设置ring的基本参数,根据Density转换成px,适配各种分辨率

    //设置各个参数,使用updateSizes()方法修改样式DEFAULT和LARGE
    private void setSizeParameters(double progressCircleWidth, double progressCircleHeight,
            double centerRadius, double strokeWidth, float arrowWidth, float arrowHeight) {
        final Ring ring = mRing;
        final DisplayMetrics metrics = mResources.getDisplayMetrics();
        final float screenDensity = metrics.density;//获取屏幕密度
        //设置各个参数,乘以screenDensity为了从dp转为px
        mWidth = progressCircleWidth * screenDensity;
        mHeight = progressCircleHeight * screenDensity;
        ring.setStrokeWidth((float) strokeWidth * screenDensity);
        ring.setCenterRadius(centerRadius * screenDensity);
        ring.setColorIndex(0);
        ring.setArrowDimensions(arrowWidth * screenDensity, arrowHeight * screenDensity);
        ring.setInsets((int) mWidth, (int) mHeight);
    }

主要的绘制工作都在ring中

         /**
         * Draw the progress spinner
         */
        public void draw(Canvas c, Rect bounds) {
            final RectF arcBounds = mTempBounds;
            arcBounds.set(bounds);
            arcBounds.inset(mStrokeInset, mStrokeInset);

            final float startAngle = (mStartTrim + mRotation) * 360;
            final float endAngle = (mEndTrim + mRotation) * 360;
            float sweepAngle = endAngle - startAngle;

            mPaint.setColor(mCurrentColor);
            //绘制弧线
            c.drawArc(arcBounds, startAngle, sweepAngle, false, mPaint);
            //绘制三角形
            drawTriangle(c, startAngle, sweepAngle, bounds);
            //当透明度小于255,透明度值和弧线三角形正好相反
            if (mAlpha < 255) {
                mCirclePaint.setColor(mBackgroundColor);
                mCirclePaint.setAlpha(255 - mAlpha);
                c.drawCircle(bounds.exactCenterX(), bounds.exactCenterY(), bounds.width() / 2,
                        mCirclePaint);
            }
        }

动画:

    //设置动画
    private void setupAnimators() {
        final Ring ring = mRing;
        final Animation animation = new Animation() {
            //第一个参数为动画的进度时间值,取值范围为[0.0f,1.0f],第二个参数Transformation记录着动画某一帧中变形的原始数据。该方法在动画的每一帧显示过程中都会被调用。
                @Override
            public void applyTransformation(float interpolatedTime, Transformation t) {
            //只在start方法中,起始角度和终止角度不一样时设置为true,当第一次动画结束后设置为false
                if (mFinishing) {
                    applyFinishTranslation(interpolatedTime, ring);//设置ring的值和颜色
                } else {
                    // The minProgressArc is calculated from 0 to create an
                    // angle that matches the stroke width.
                    final float minProgressArc = getMinProgressArc(ring);
                    final float startingEndTrim = ring.getStartingEndTrim();
                    final float startingTrim = ring.getStartingStartTrim();
                    final float startingRotation = ring.getStartingRotation();

                    updateRingColor(interpolatedTime, ring);

                    // Moving the start trim only occurs in the first 50% of a
                    // single ring animation
                    //前面半部分只设置起点的值
                    if (interpolatedTime <= START_TRIM_DURATION_OFFSET) {
                        // scale the interpolatedTime so that the full
                        // transformation from 0 - 1 takes place in the
                        // remaining time
                        final float scaledTime = (interpolatedTime)
                                / (1.0f - START_TRIM_DURATION_OFFSET);
                        final float startTrim = startingTrim
                                + ((MAX_PROGRESS_ARC - minProgressArc) * MATERIAL_INTERPOLATOR
                                        .getInterpolation(scaledTime));
                        ring.setStartTrim(startTrim);
                    }

                    // Moving the end trim starts after 50% of a single ring
                    // animation completes
                     // 后半部分只设置终点的值
                    if (interpolatedTime > END_TRIM_START_DELAY_OFFSET) {
                        // scale the interpolatedTime so that the full
                        // transformation from 0 - 1 takes place in the
                        // remaining time
                        final float minArc = MAX_PROGRESS_ARC - minProgressArc;
                        float scaledTime = (interpolatedTime - START_TRIM_DURATION_OFFSET)
                                / (1.0f - START_TRIM_DURATION_OFFSET);
                        final float endTrim = startingEndTrim
                                + (minArc * MATERIAL_INTERPOLATOR.getInterpolation(scaledTime));
                        ring.setEndTrim(endTrim);
                    }

                     //没看出来有什么作用。。
                    final float rotation = startingRotation + (0.25f * interpolatedTime);
                    ring.setRotation(rotation);
                    //总角度为1080,分5圈转完
                    // ((FULL_ROTATION / NUM_POINTS) * interpolatedTime) 当前动画需要转的角度
                    //(FULL_ROTATION * (mRotationCount / NUM_POINTS)) 承接上一圈转的角度
                    //如第一圈,角度从0~216,第二圈216~432...第五圈864~1080。在draw(canvas)中设置canvas角度旋转
                    float groupRotation = ((FULL_ROTATION / NUM_POINTS) * interpolatedTime)
                            + (FULL_ROTATION * (mRotationCount / NUM_POINTS));
                    setRotation(groupRotation);//设置旋转的角度并更新,调用draw()
                }
            }
        };
        animation.setRepeatCount(Animation.INFINITE);
        animation.setRepeatMode(Animation.RESTART);
        animation.setInterpolator(LINEAR_INTERPOLATOR);
        animation.setAnimationListener(new Animation.AnimationListener() {

                @Override
            public void onAnimationStart(Animation animation) {
                mRotationCount = 0;
            }

                @Override
            public void onAnimationEnd(Animation animation) {
                // do nothing
            }

                @Override
            public void onAnimationRepeat(Animation animation) {
                //记录完成动画时的角度信息
                ring.storeOriginals();
                //下一个颜色
                ring.goToNextColor();
                ring.setStartTrim(ring.getEndTrim());
                if (mFinishing) {
                    //完成第一个动画,关闭箭头,SwipeRefreshLayout中向下拉完成后
                    mFinishing = false;
                    animation.setDuration(ANIMATION_DURATION);
                    ring.setShowArrow(false);
                } else {
                    mRotationCount = (mRotationCount + 1) % (NUM_POINTS);
                }
            }
        });
        mAnimation = animation;
    }

第一遍动画调用applyFinishTranslation完成,之后关闭箭头,开始新的动画,每次的动画是前50%只更改起点位置,后50%只更改终点位置,通过一系列的计算,旋转canvas
参考资料:http://blog.csdn.net/tyzlmjj/article/details/50557397

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值