/** * 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); } } }
源码注释:Animation的一些应用
最新推荐文章于 2021-04-09 17:38:06 发布