一個簡單的載入動畫(二)

月光邊境發表於2018-01-18

最終效果圖:

一個簡單的載入動畫(二)

程式碼:

public class PointerLoadingView extends View {
        /**
         * 外圈圓心寬度
         */
        private int ringWidth = dip2px(6);
        /**
         * 圓心和圓環的顏色
         */
        private int primaryColor = Color.parseColor("#4b546a");
        /**
         * 指標的顏色
         */
        private int pointerColor = Color.parseColor("#70c7d4");
        /**
         * 大圓心半徑
         */
        private int bigCircleRadius = dip2px(10);
        /**
         * 小圓心的半徑
         */
        private int smallCircleRadius = dip2px(5);
        /**
         * 指標轉動角度
         */
        private int pointerAngle = 0;
        /**
         * 圓弧的轉動半徑
         */
        private int arcAngle = 45;
        /**
         * 正方形控制元件的尺寸
         */
        private int mSquareSize;

        public PointerLoadingView(Context context) {
            super(context);
            init();
        }

        public PointerLoadingView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }

        public PointerLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }

        Paint bigCirclePaint;
        Paint smallCirclePaint;
        Paint ringPaint;
        Paint pointerPaint;
        Paint arcPaint;
        Path path;

        private void init() {
            //大圓心畫筆
            bigCirclePaint = new Paint();
            bigCirclePaint.setAntiAlias(true);
            bigCirclePaint.setColor(pointerColor);
            //小圓心畫筆
            smallCirclePaint = new Paint();
            smallCirclePaint.setAntiAlias(true);
            smallCirclePaint.setColor(primaryColor);
            //圓環畫筆
            ringPaint = new Paint();
            ringPaint.setAntiAlias(true);
            ringPaint.setStyle(Paint.Style.STROKE);
            ringPaint.setStrokeWidth(ringWidth);
            ringPaint.setColor(primaryColor);
            //圓弧畫筆
            arcPaint = new Paint();
            arcPaint.setAntiAlias(true);
            arcPaint.setStyle(Paint.Style.STROKE);
            arcPaint.setStrokeWidth(ringWidth);
            arcPaint.setStrokeCap(Paint.Cap.ROUND);
            arcPaint.setColor(pointerColor);
            //指標畫筆
            pointerPaint = new Paint();
            pointerPaint.setAntiAlias(true);
            pointerPaint.setStyle(Paint.Style.FILL);
            pointerPaint.setColor(pointerColor);
            path = new Path();
        }

        /**
         * 動畫是否在播放
         */
        private boolean animPlaying = false;

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            if (mSquareSize == 0) return;
            canvas.save();
            //畫三角指標
            canvas.translate(mSquareSize / 2, mSquareSize / 2);
            canvas.rotate(pointerAngle);
            path.moveTo(-smallCircleRadius - 1, 0);
            path.lineTo(0, -mSquareSize / 2 + 15);
            path.lineTo(smallCircleRadius + 1, 0);
            canvas.drawPath(path, pointerPaint);
            //畫大圓心
            canvas.drawCircle(0, 0, bigCircleRadius, bigCirclePaint);
            //畫圓環
            canvas.drawCircle(0, 0, mSquareSize / 2 - 10, ringPaint);
            //畫小圓心
            canvas.drawCircle(0, 0, smallCircleRadius, smallCirclePaint);
            //畫圓弧
            RectF rectF = new RectF(-mSquareSize / 2 + 10, -mSquareSize / 2 + 10, mSquareSize / 2 - 10, mSquareSize / 2 - 10);
            canvas.drawArc(rectF, 270, arcAngle, false, arcPaint);
            //合併畫布
            canvas.restore();
            if (!animPlaying)
                startAnim();
        }

        private void startAnim() {
            final ValueAnimator animator = ValueAnimator.ofInt(1);
            animator.setDuration(1000);
            animator.setInterpolator(new AccelerateDecelerateInterpolator());
            animator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animator) {
                    animPlaying = true;
                }

                @Override
                public void onAnimationEnd(Animator animator) {
                    animPlaying = false;
                }

                @Override
                public void onAnimationCancel(Animator animator) {
                }

                @Override
                public void onAnimationRepeat(Animator animator) {
                }
            });
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    float fraction = animator.getAnimatedFraction();
                    pointerAngle = (int) (360.0f * fraction);
                    if (fraction <= 0.25)
                        arcAngle = (int) (fraction * 240);
                    else if (0.25 < fraction && fraction <= 0.75)
                        arcAngle = (int) (-240 * fraction + 120);
                    else arcAngle = (int) (240 * fraction - 240);
                    Log.i("TAG", arcAngle + ":fraction:" + fraction);
                    invalidate();
                }
            });
            animator.start();
        }

        public int dip2px(float dpValue) {
            final float scale = Resources.getSystem().getDisplayMetrics().density;
            return (int) (dpValue * scale + 0.5f);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, widthMeasureSpec);
        }

        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mSquareSize = w;
            Log.i(getClass().getSimpleName(), "w:" + w + ",h:" + h);
        }
    }
複製程式碼

相關文章