視差動畫 雅虎新聞摘要載入

紅橙Darren發表於2017-12-14

1. 效果


雅虎新聞摘要載入

太多太多的評論我其實是不會回的,如果要說什麼只能說抱歉。我承認很多視訊連結沒那麼好找,但是你如果留意用心了,肯定能獲取到以前所有的直播視訊連結。

2.分析和實現


2.1 效果分析:

寫了那麼多次效果,這個實現起來應該是個小 case ,留意觀察有三部分動畫   1. 旋轉動畫,六個小球在不斷地旋轉   2. 位移動畫,六個小球往中心點聚合   3. 擴散動畫,當小球移動的最中心就開始擴散

2.2 分步實現:

1. 旋轉動畫,六個小球在不斷地旋轉

     /**
     * 繪製小圓的旋轉動畫
     */
    private class RotationState extends SplashState {
        private ValueAnimator mAnimator;

        public RotationState() {
            // 屬性動畫
            mAnimator = ValueAnimator.ofFloat(0, (float) Math.PI * 2);
            mAnimator.setDuration(ROTATION_ANIMATION_TIME);
            mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    // 不斷獲取值 當前大圓旋轉的角度
                    mCurrentRotationAngle = (float) animation.getAnimatedValue();
                    // 提醒View重新繪製
                    invalidate();
                }
            });
            mAnimator.setRepeatCount(-1);
            mAnimator.setInterpolator(new LinearInterpolator());
            // 開始計算
            mAnimator.start();
        }

        @Override
        public void draw(Canvas canvas) {
            canvas.drawColor(mSplashColor);
            // 繪製六個小圓 座標
            float preAngle = (float) (2 * Math.PI / mCircleColors.length);
            for (int i = 0; i < mCircleColors.length; i++) {
                mPaint.setColor(mCircleColors[i]);
                // 初始角度 + 當前旋轉的角度
                double angle = i * preAngle + mCurrentRotationAngle;
                float cx = (float) (mCenterX + mRotationRadius * Math.cos(angle));
                float cy = (float) (mCenterY + mRotationRadius * Math.sin(angle));
                canvas.drawCircle(cx, cy, mCircleRadius, mPaint);
            }
        }

        public void cancelAnimator() {
            mAnimator.cancel();
            mAnimator = null;
        }
    }
複製程式碼

2. 位移動畫,六個小球往中心點靠攏

	/**
     * 繪製小圓的聚合動畫
     */
    private class MergeState extends SplashState {
        private ValueAnimator mAnimator;

        public MergeState() {
            // 屬性動畫
            mAnimator = ValueAnimator.ofFloat(mRotationRadius, 0);
            mAnimator.setDuration(SPLASH_ANIMATION_TIME / 2);
            mAnimator.setInterpolator(new AnticipateInterpolator(6f));
            mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    // 不斷獲取值 當前大圓旋轉的角度
                    mCurrentRotationRadius = (float) animation.getAnimatedValue();
                    // 提醒View重新繪製
                    invalidate();
                }
            });

            mAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    mSplashState = new ExpandingState();
                }
            });

            // 開始計算
            mAnimator.start();
        }

        @Override
        public void draw(Canvas canvas) {
            canvas.drawColor(mSplashColor);
            // 繪製六個小圓 座標
            float preAngle = (float) (2 * Math.PI / mCircleColors.length);
            for (int i = 0; i < mCircleColors.length; i++) {
                mPaint.setColor(mCircleColors[i]);
                // 初始角度 + 當前旋轉的角度
                double angle = i * preAngle + mCurrentRotationAngle;
                float cx = (float) (mCenterX + mCurrentRotationRadius * Math.cos(angle));
                float cy = (float) (mCenterY + mCurrentRotationRadius * Math.sin(angle));
                canvas.drawCircle(cx, cy, mCircleRadius, mPaint);
            }
        }
    }
複製程式碼

3. 擴散動畫,當小球移動的最中心就開始擴散

    /**
     * 繪製小圓的擴散動畫
     */
    private class ExpandingState extends SplashState {
        private ValueAnimator mAnimator;

        public ExpandingState() {
            // 屬性動畫
            mAnimator = ValueAnimator.ofFloat(0, mDiagonalDist);
            mAnimator.setDuration(SPLASH_ANIMATION_TIME/2);
            mAnimator.setInterpolator(new AccelerateInterpolator());
            mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    // 不斷獲取值 當前大圓旋轉的角度
                    mHoleRadius = (float) animation.getAnimatedValue();
                    // 提醒View重新繪製
                    invalidate();
                }
            });
            // 開始計算
            mAnimator.start();
        }

        @Override
        public void draw(Canvas canvas) {
            if (mHoleRadius > 0) {
                float strokeWidth = mDiagonalDist - mHoleRadius;
                mPaintBackground.setStrokeWidth(strokeWidth);
                float radius = mHoleRadius + strokeWidth / 2;
                canvas.drawCircle(mCenterX, mCenterY, radius, mPaintBackground);
            } else {
                canvas.drawColor(mSplashColor);
            }
        }
    }
複製程式碼

這期是自定義 View 部分的最後一次寫效果了,寫得也比較簡單,因為畢竟前面寫過那麼多次,關於畫筆繪製和屬性動畫我就不再詳講了。

所有分享大綱:Android進階之旅 - 自定義View篇

視訊講解地址:http://pan.baidu.com/s/1mhVUimO

相關文章