源码注释:Animation的一些应用

17 篇文章 0 订阅
/**
 * Animation例子
 * <p>
 * PositionAndSizeAnimation
 * PieRenderer
 * BaseCardView
 * SwitchCompat
 * AppTransition
 * FloatingToolbar
 * CurvedTranslateAnimation
 * BaseCardView
 * CircularProgressDrawable
 * MaterialProgressDrawable
 * ClipRectAnimation
 */


class Rotate3dAnimation extends Animation {
    public void applyRotation(int position, float start, float end) {
        // Find the center of the container 
        final float centerX = mContainer.getWidth() / 2.0f;
        final float centerY = mContainer.getHeight() / 2.0f;
        // Create a new 3D rotation with the supplied parameter 
        // The animation listener is used to trigger the next animation 
        final Rotate3dAnimation rotation = new Rotate3dAnimation(start, end, centerX, centerY, 310.0f, true);
        rotation.setDuration(500);
        rotation.setFillAfter(true);
        rotation.setInterpolator(new AccelerateInterpolator());
        rotation.setAnimationListener(new DisplayNextView(position));
        mContainer.startAnimation(rotation);
    } /*public void onItemClick(AdapterView<?> parent, View v, int position, long id) { // Pre-load the image then start the animation mImageView.setImageResource(PHOTOS_RESOURCES[position]); applyRotation(position, 0, 90); }*/

    private final float mFromDegrees;
    private final float mToDegrees;
    private final float mCenterX;
    private final float mCenterY;
    private final float mDepthZ;
    private final boolean mReverse;
    private Camera mCamera;

    /**
     * Creates a new 3D rotation on the Y axis. The rotation is defined by its * start angle and its end angle. Both angles are in degrees. The rotation * is performed around a center point on the 2D space, definied by a pair * of X and Y coordinates, called centerX and centerY. When the animation * starts, a translation on the Z axis (depth) is performed. The length * of the translation can be specified, as well as whether the translation * should be reversed in time. * * @param fromDegrees the start angle of the 3D rotation * @param toDegrees the end angle of the 3D rotation * @param centerX the X center of the 3D rotation * @param centerY the Y center of the 3D rotation * @param reverse true if the translation should be reversed, false otherwise
     */
    public Rotate3dAnimation(float fromDegrees, float toDegrees, float centerX, float centerY, float depthZ, boolean reverse) {
        mFromDegrees = fromDegrees;
        mToDegrees = toDegrees;
        mCenterX = centerX;
        mCenterY = centerY;
        mDepthZ = depthZ;
        mReverse = reverse;
    }

    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        mCamera = new Camera();
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        final float fromDegrees = mFromDegrees;
        float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);
        final float centerX = mCenterX;
        final float centerY = mCenterY;
        final Camera camera = mCamera;
        final Matrix matrix = t.getMatrix();
        camera.save();
        if (mReverse) {
            camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
        } else {
            camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
        }
        camera.rotateY(degrees);
        camera.getMatrix(matrix);
        camera.restore();
        matrix.preTranslate(-centerX, -centerY);
        matrix.postTranslate(centerX, centerY);
    }
}


class ThumbAnimation extends Animation { /*private void animateThumbToCheckedState(boolean newCheckedState) { mPositionAnimator = new ThumbAnimation(mThumbPosition, newCheckedState ? 1 : 0); mPositionAnimator.setDuration(THUMB_ANIMATION_DURATION); startAnimation(mPositionAnimator); }*/
    final float mStartPosition;
    final float mEndPosition;
    final float mDiff;

    private ThumbAnimation(float startPosition, float endPosition) {
        mStartPosition = startPosition;
        mEndPosition = endPosition;
        mDiff = endPosition - startPosition;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        setThumbPosition(mStartPosition + (mDiff * interpolatedTime));
    }
}


class PositionAndSizeAnimation extends Animation implements HandleLayout {
    private final View mView;
    private final float mStartX, mStartY, mDeltaX, mDeltaY;
    private final int mStartWidth, mStartHeight, mDeltaWidth, mDeltaHeight;

    public PositionAndSizeAnimation(View view, int x, int y, int width, int height) {
        mView = view;
        mStartX = view.getX();
        mStartY = view.getY();
        mStartWidth = view.getWidth();
        mStartHeight = view.getHeight();
        mDeltaX = x - mStartX;
        mDeltaY = y - mStartY;
        mDeltaWidth = width - mStartWidth;
        mDeltaHeight = height - mStartHeight;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        float newX = mStartX + mDeltaX * interpolatedTime;
        float newY = mStartY + mDeltaY * interpolatedTime;
        float newWidth = mStartWidth + mDeltaWidth * interpolatedTime;
        float newHeight = mStartHeight + mDeltaHeight * interpolatedTime;
        mView.layout(Math.round(newX), Math.round(newY), Math.round(newX + newWidth), Math.round(newY + newHeight));
    }

    @Override
    public boolean willChangeBounds() {
        return true;
    }
}


/* package */ class OpacityAnimation extends Animation {

    static class OpacityAnimationListener implements AnimationListener {

        private final View mView;
        private boolean mLayerTypeChanged = false;

        public OpacityAnimationListener(View view) {
            mView = view;
        }

        @Override
        public void onAnimationStart(Animation animation) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                // ?
                if (mView.hasOverlappingRendering() &&
                        mView.getLayerType() == View.LAYER_TYPE_NONE) {
                    mLayerTypeChanged = true;
                    mView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
                }
            }
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            if (mLayerTypeChanged) {
                mView.setLayerType(View.LAYER_TYPE_NONE, null);
            }
        }

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

    private final View mView;
    private final float mStartOpacity, mDeltaOpacity;

    public OpacityAnimation(View view, float startOpacity, float endOpacity) {
        mView = view;
        mStartOpacity = startOpacity;
        mDeltaOpacity = endOpacity - startOpacity;

        setAnimationListener(new OpacityAnimationListener(view));
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        mView.setAlpha(mStartOpacity + mDeltaOpacity * interpolatedTime);
    }

    @Override
    public boolean willChangeBounds() {
        return false;
    }
}



/**
 * NineoldAndroid的核心原理:
 * 低版本使用Animation实现视觉上的位置移动:
 */


final /*static*/ class AnimatorProxy
        extends Animation {
    public static final boolean NEEDS_PROXY = Integer.valueOf(Build.VERSION.SDK).intValue() < 11;
    private static final WeakHashMap<View, AnimatorProxy> PROXIES = new WeakHashMap();
    private final WeakReference<View> mView;

    public static AnimatorProxy wrap(View view) {
        AnimatorProxy proxy = (AnimatorProxy) PROXIES.get(view);
        if ((proxy == null) || (proxy != view.getAnimation())) {
            proxy = new AnimatorProxy(view);
            PROXIES.put(view, proxy);
        }
        return proxy;
    }

    private final Camera mCamera = new Camera();
    private boolean mHasPivot;
    private float mAlpha = 1.0F;
    private float mPivotX;
    private float mPivotY;
    private float mRotationX;
    private float mRotationY;
    private float mRotationZ;
    private float mScaleX = 1.0F;
    private float mScaleY = 1.0F;
    private float mTranslationX;
    private float mTranslationY;
    private final RectF mBefore = new RectF();
    private final RectF mAfter = new RectF();
    private final Matrix mTempMatrix = new Matrix();

    private AnimatorProxy(View view) {
        setDuration(0L);
        setFillAfter(true);
        view.setAnimation(this);
        this.mView = new WeakReference(view);
    }

    public float getAlpha() {
        return this.mAlpha;
    }

    public void setAlpha(float alpha) {
        if (this.mAlpha != alpha) {
            this.mAlpha = alpha;
            View view = (View) this.mView.get();
            if (view != null) {
                view.invalidate();
            }
        }
    }

    public float getPivotX() {
        return this.mPivotX;
    }

    public void setPivotX(float pivotX) {
        if ((!this.mHasPivot) || (this.mPivotX != pivotX)) {
            prepareForUpdate();
            this.mHasPivot = true;
            this.mPivotX = pivotX;
            invalidateAfterUpdate();
        }
    }

    public float getPivotY() {
        return this.mPivotY;
    }

    public void setPivotY(float pivotY) {
        if ((!this.mHasPivot) || (this.mPivotY != pivotY)) {
            prepareForUpdate();
            this.mHasPivot = true;
            this.mPivotY = pivotY;
            invalidateAfterUpdate();
        }
    }

    public float getRotation() {
        return this.mRotationZ;
    }

    public void setRotation(float rotation) {
        if (this.mRotationZ != rotation) {
            prepareForUpdate();
            this.mRotationZ = rotation;
            invalidateAfterUpdate();
        }
    }

    public float getRotationX() {
        return this.mRotationX;
    }

    public void setRotationX(float rotationX) {
        if (this.mRotationX != rotationX) {
            prepareForUpdate();
            this.mRotationX = rotationX;
            invalidateAfterUpdate();
        }
    }

    public float getRotationY() {
        return this.mRotationY;
    }

    public void setRotationY(float rotationY) {
        if (this.mRotationY != rotationY) {
            prepareForUpdate();
            this.mRotationY = rotationY;
            invalidateAfterUpdate();
        }
    }

    public float getScaleX() {
        return this.mScaleX;
    }

    public void setScaleX(float scaleX) {
        if (this.mScaleX != scaleX) {
            prepareForUpdate();
            this.mScaleX = scaleX;
            invalidateAfterUpdate();
        }
    }

    public float getScaleY() {
        return this.mScaleY;
    }

    public void setScaleY(float scaleY) {
        if (this.mScaleY != scaleY) {
            prepareForUpdate();
            this.mScaleY = scaleY;
            invalidateAfterUpdate();
        }
    }

    public int getScrollX() {
        View view = (View) this.mView.get();
        if (view == null) {
            return 0;
        }
        return view.getScrollX();
    }

    public void setScrollX(int value) {
        View view = (View) this.mView.get();
        if (view != null) {
            view.scrollTo(value, view.getScrollY());
        }
    }

    public int getScrollY() {
        View view = (View) this.mView.get();
        if (view == null) {
            return 0;
        }
        return view.getScrollY();
    }

    public void setScrollY(int value) {
        View view = (View) this.mView.get();
        if (view != null) {
            view.scrollTo(view.getScrollX(), value);
        }
    }

    public float getTranslationX() {
        return this.mTranslationX;
    }

    public void setTranslationX(float translationX) {
        if (this.mTranslationX != translationX) {
            prepareForUpdate();
            this.mTranslationX = translationX;
            invalidateAfterUpdate();
        }
    }

    public float getTranslationY() {
        return this.mTranslationY;
    }

    public void setTranslationY(float translationY) {
        if (this.mTranslationY != translationY) {
            prepareForUpdate();
            this.mTranslationY = translationY;
            invalidateAfterUpdate();
        }
    }

    public float getX() {
        View view = (View) this.mView.get();
        if (view == null) {
            return 0.0F;
        }
        return view.getLeft() + this.mTranslationX;
    }

    public void setX(float x) {
        View view = (View) this.mView.get();
        if (view != null) {
            setTranslationX(x - view.getLeft());
        }
    }

    public float getY() {
        View view = (View) this.mView.get();
        if (view == null) {
            return 0.0F;
        }
        return view.getTop() + this.mTranslationY;
    }

    public void setY(float y) {
        View view = (View) this.mView.get();
        if (view != null) {
            setTranslationY(y - view.getTop());
        }
    }

    private void prepareForUpdate() {
        View view = (View) this.mView.get();
        if (view != null) {
            computeRect(this.mBefore, view);
        }
    }

    private void invalidateAfterUpdate() {
        View view = (View) this.mView.get();
        if ((view == null) || (view.getParent() == null)) {
            return;
        }
        RectF after = this.mAfter;
        computeRect(after, view);
        after.union(this.mBefore);

        ((View) view.getParent())
                .invalidate((int) Math.floor(after.left), (int) Math.floor(after.top), (int) Math.ceil(after.right), (int) Math.ceil(after.bottom));
    }

    // 核心代码:获取变化的区域
    private void computeRect(RectF r, View view) {
        float w = view.getWidth();
        float h = view.getHeight();

        r.set(0.0F, 0.0F, w, h);

        Matrix m = this.mTempMatrix;
        m.reset();
        transformMatrix(m, view);
        this.mTempMatrix.mapRect(r);

        r.offset(view.getLeft(), view.getTop());
        if (r.right < r.left) {
            float f = r.right;
            r.right = r.left;
            r.left = f;
        }
        if (r.bottom < r.top) {
            float f = r.top;
            r.top = r.bottom;
            r.bottom = f;
        }
    }

    // 核心代码:坐标变换
    private void transformMatrix(Matrix m, View view) {
        float w = view.getWidth();
        float h = view.getHeight();
        boolean hasPivot = this.mHasPivot;
        float pX = hasPivot ? this.mPivotX : w / 2.0F;
        float pY = hasPivot ? this.mPivotY : h / 2.0F;

        float rX = this.mRotationX;
        float rY = this.mRotationY;
        float rZ = this.mRotationZ;
        if ((rX != 0.0F) || (rY != 0.0F) || (rZ != 0.0F)) {
            // 旋转:
            // T(pX, pY) * R(rx, ry) * T(-pX, -pY)
            // 先移动px,py的反向距离,再旋转,再移动回来
            Camera camera = this.mCamera;
            camera.save();
            camera.rotateX(rX);
            camera.rotateY(rY);
            camera.rotateZ(-rZ);
            camera.getMatrix(m);
            camera.restore();

            m.preTranslate(-pX, -pY);
            m.postTranslate(pX, pY);
        }
        float sX = this.mScaleX;
        float sY = this.mScaleY;
        if ((sX != 1.0F) || (sY != 1.0F)) {
            // 缩放
            // 先直接参考(0, 0)缩放,然后平移
            m.postScale(sX, sY);
            float sPX = -(pX / w) * (sX * w - w);
            float sPY = -(pY / h) * (sY * h - h);
            m.postTranslate(sPX, sPY);
        }
        // 平移不需要参考点
        m.postTranslate(this.mTranslationX, this.mTranslationY);
    }
    // View.draw(Canvas canvas, ViewGroup parent, long drawingTime)
    // View.applyLegacyAnimation
    // Animation.getTransformation/getInvalidateRegion
    // invalidate

    protected void applyTransformation(float interpolatedTime, Transformation t) {
        View view = (View) this.mView.get();
        if (view != null) {
            t.setAlpha(this.mAlpha);
            transformMatrix(t.getMatrix(), view);
        }
    }
}


 /*static*/ final class ViewHelper {
    public static float getAlpha(View view) {
        return AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(view).getAlpha() : Honeycomb.getAlpha(view);
    }

    public static void setAlpha(View view, float alpha) {
        if (AnimatorProxy.NEEDS_PROXY) {
            AnimatorProxy.wrap(view).setAlpha(alpha);
        } else {
            Honeycomb.setAlpha(view, alpha);
        }
    }

    public static float getPivotX(View view) {
        return AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(view).getPivotX() : Honeycomb.getPivotX(view);
    }

    public static void setPivotX(View view, float pivotX) {
        if (AnimatorProxy.NEEDS_PROXY) {
            AnimatorProxy.wrap(view).setPivotX(pivotX);
        } else {
            Honeycomb.setPivotX(view, pivotX);
        }
    }

    public static float getPivotY(View view) {
        return AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(view).getPivotY() : Honeycomb.getPivotY(view);
    }

    public static void setPivotY(View view, float pivotY) {
        if (AnimatorProxy.NEEDS_PROXY) {
            AnimatorProxy.wrap(view).setPivotY(pivotY);
        } else {
            Honeycomb.setPivotY(view, pivotY);
        }
    }

    public static float getRotation(View view) {
        return AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(view).getRotation() : Honeycomb.getRotation(view);
    }

    public static void setRotation(View view, float rotation) {
        if (AnimatorProxy.NEEDS_PROXY) {
            AnimatorProxy.wrap(view).setRotation(rotation);
        } else {
            Honeycomb.setRotation(view, rotation);
        }
    }

    public static float getRotationX(View view) {
        return AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(view).getRotationX() : Honeycomb.getRotationX(view);
    }

    public static void setRotationX(View view, float rotationX) {
        if (AnimatorProxy.NEEDS_PROXY) {
            AnimatorProxy.wrap(view).setRotationX(rotationX);
        } else {
            Honeycomb.setRotationX(view, rotationX);
        }
    }

    public static float getRotationY(View view) {
        return AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(view).getRotationY() : Honeycomb.getRotationY(view);
    }

    public static void setRotationY(View view, float rotationY) {
        if (AnimatorProxy.NEEDS_PROXY) {
            AnimatorProxy.wrap(view).setRotationY(rotationY);
        } else {
            Honeycomb.setRotationY(view, rotationY);
        }
    }

    public static float getScaleX(View view) {
        return AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(view).getScaleX() : Honeycomb.getScaleX(view);
    }

    public static void setScaleX(View view, float scaleX) {
        if (AnimatorProxy.NEEDS_PROXY) {
            AnimatorProxy.wrap(view).setScaleX(scaleX);
        } else {
            Honeycomb.setScaleX(view, scaleX);
        }
    }

    public static float getScaleY(View view) {
        return AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(view).getScaleY() : Honeycomb.getScaleY(view);
    }

    public static void setScaleY(View view, float scaleY) {
        if (AnimatorProxy.NEEDS_PROXY) {
            AnimatorProxy.wrap(view).setScaleY(scaleY);
        } else {
            Honeycomb.setScaleY(view, scaleY);
        }
    }

    public static float getScrollX(View view) {
        return AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(view).getScrollX() : Honeycomb.getScrollX(view);
    }

    public static void setScrollX(View view, int scrollX) {
        if (AnimatorProxy.NEEDS_PROXY) {
            AnimatorProxy.wrap(view).setScrollX(scrollX);
        } else {
            Honeycomb.setScrollX(view, scrollX);
        }
    }

    public static float getScrollY(View view) {
        return AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(view).getScrollY() : Honeycomb.getScrollY(view);
    }

    public static void setScrollY(View view, int scrollY) {
        if (AnimatorProxy.NEEDS_PROXY) {
            AnimatorProxy.wrap(view).setScrollY(scrollY);
        } else {
            Honeycomb.setScrollY(view, scrollY);
        }
    }

    public static float getTranslationX(View view) {
        return AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(view).getTranslationX() : Honeycomb.getTranslationX(view);
    }

    public static void setTranslationX(View view, float translationX) {
        if (AnimatorProxy.NEEDS_PROXY) {
            AnimatorProxy.wrap(view).setTranslationX(translationX);
        } else {
            Honeycomb.setTranslationX(view, translationX);
        }
    }

    public static float getTranslationY(View view) {
        return AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(view).getTranslationY() : Honeycomb.getTranslationY(view);
    }

    public static void setTranslationY(View view, float translationY) {
        if (AnimatorProxy.NEEDS_PROXY) {
            AnimatorProxy.wrap(view).setTranslationY(translationY);
        } else {
            Honeycomb.setTranslationY(view, translationY);
        }
    }

    public static float getX(View view) {
        return AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(view).getX() : Honeycomb.getX(view);
    }

    public static void setX(View view, float x) {
        if (AnimatorProxy.NEEDS_PROXY) {
            AnimatorProxy.wrap(view).setX(x);
        } else {
            Honeycomb.setX(view, x);
        }
    }

    public static float getY(View view) {
        return AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(view).getY() : Honeycomb.getY(view);
    }

    public static void setY(View view, float y) {
        if (AnimatorProxy.NEEDS_PROXY) {
            AnimatorProxy.wrap(view).setY(y);
        } else {
            Honeycomb.setY(view, y);
        }
    }

    private static final class Honeycomb {
        static float getAlpha(View view) {
            return view.getAlpha();
        }

        static void setAlpha(View view, float alpha) {
            view.setAlpha(alpha);
        }

        static float getPivotX(View view) {
            return view.getPivotX();
        }

        static void setPivotX(View view, float pivotX) {
            view.setPivotX(pivotX);
        }

        static float getPivotY(View view) {
            return view.getPivotY();
        }

        static void setPivotY(View view, float pivotY) {
            view.setPivotY(pivotY);
        }

        static float getRotation(View view) {
            return view.getRotation();
        }

        static void setRotation(View view, float rotation) {
            view.setRotation(rotation);
        }

        static float getRotationX(View view) {
            return view.getRotationX();
        }

        static void setRotationX(View view, float rotationX) {
            view.setRotationX(rotationX);
        }

        static float getRotationY(View view) {
            return view.getRotationY();
        }

        static void setRotationY(View view, float rotationY) {
            view.setRotationY(rotationY);
        }

        static float getScaleX(View view) {
            return view.getScaleX();
        }

        static void setScaleX(View view, float scaleX) {
            view.setScaleX(scaleX);
        }

        static float getScaleY(View view) {
            return view.getScaleY();
        }

        static void setScaleY(View view, float scaleY) {
            view.setScaleY(scaleY);
        }

        static float getScrollX(View view) {
            return view.getScrollX();
        }

        static void setScrollX(View view, int scrollX) {
            view.setScrollX(scrollX);
        }

        static float getScrollY(View view) {
            return view.getScrollY();
        }

        static void setScrollY(View view, int scrollY) {
            view.setScrollY(scrollY);
        }

        static float getTranslationX(View view) {
            return view.getTranslationX();
        }

        static void setTranslationX(View view, float translationX) {
            view.setTranslationX(translationX);
        }

        static float getTranslationY(View view) {
            return view.getTranslationY();
        }

        static void setTranslationY(View view, float translationY) {
            view.setTranslationY(translationY);
        }

        static float getX(View view) {
            return view.getX();
        }

        static void setX(View view, float x) {
            view.setX(x);
        }

        static float getY(View view) {
            return view.getY();
        }

        static void setY(View view, float y) {
            view.setY(y);
        }
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值