视差动画 雅虎新闻摘要加载

1,290 阅读2分钟

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