package com.mjun.mtransition; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.animation.Interpolator; import com.mjun.mtransition.anim.Transition; import com.mjun.mtransition.view.CloneView; import junit.framework.Assert; /** * @author huijun.zhj * * 动画数据的基本单位,每一个MTransitionView都有对应的一个View * 如果你的View需要在场景切换时做动画,则通过 {@link MTransitionPage#addTransitionView(String, View)}生成 {@link MTransitionView}实例 * 同时可以调用该类的其他函数,如 {@link #alpha(float, float)}、 {@link #translateX(int, int)}等api,设置执行的动画效果 * * The basic unit of Transiton data, each MTransitionView has a corresponding View * If your View needs to transit during scene change(Activity change), generate a {@link MTransitionView} * instance via {@link MTransitionPage#addTransitionView(String, View)} * And you can call other methods of this class, such as {@link #alpha(float, float)}, * {@link #translateX(int, int)} and other api, to set the Transition effect */ public class MTransitionView implements ITransitional { /** * 存储该View执行的动画路径数据 * Store the Transition path data of the View */ private Transition mTransition = new Transition(); private View mContent = null; /** * 该MTransitionView对应真正的View * * The view which the MTransitionView corresponds to */ private View mSourceView = null; /** * {@link #mSourceView} 在屏幕上的位置信息 * {@link #mSourceView} location on the screen */ int[] mLocation = new int[2]; int[] mParentLocation = null; int mInitTransX = 0; int mInitTransY = 0; /** * 调用 {@link #transitTo(MTransitionView)} 所需要 * Required for calling {@link #transitTo(MTransitionView)} */ MTransitionView mTargetView; /** * 该MTransitionView是否其他MTransitionView的动画目标 * Whether the MTransitionView is the transit target of other MTransitionView */ boolean mIsTarget = false; boolean mChangeSize = false; MTransitionPage mBelongPage; public MTransitionView(View source) { Assert.assertNotNull(source); mSourceView = source; mContent = new CloneView(source.getContext()); // TODO:处理有replace的情况 ((CloneView) mContent).setSourceView(source); source.getLocationInWindow(mLocation); } /** * 动画执行时回调 * Callback when Transition is executed * @param playTime 动画已经执行的时长 The time of long the Transition has been performed * @param progress 动画已经执行的进度 The progress of the Transition has been performed */ @Override public void onTransitProgress(long playTime, float progress) { Log.d("zhj2", "onTransitProgress : " + this + " " + mContent); float alpha = mTransition.getAlpha(playTime, progress); mContent.setAlpha(alpha); float scaleX = mTransition.getScaleX(playTime, progress); mContent.setScaleX(scaleX); float scaleY = mTransition.getScaleY(playTime, progress); mContent.setScaleY(scaleY); int transX = mTransition.getTranslateX(playTime, progress); mContent.setTranslationX(mInitTransX + transX); int transY = mTransition.getTranslateY(playTime, progress); mContent.setTranslationY(mInitTransY + transY); int rotateX = mTransition.getRotateX(playTime, progress); mContent.setRotationX(rotateX); int rotateY = mTransition.getRotateY(playTime, progress); mContent.setRotationY(rotateY); int rotateZ = mTransition.getRotateZ(playTime, progress); mContent.setRotation(rotateZ); if (mContent instanceof ITransitional) { ((ITransitional) mContent).onTransitProgress(playTime, progress); } invalidate(); } void invalidate() { mContent.invalidate(); } /** * 动画开始时回调 * Callback when Transition start */ @Override public void onTransitStart() { } /** * 动画结束时回调 * Callback when Transition end */ @Override public void onTransitEnd() { } /** * @see #replaceBy(ITransitional, LayoutParams) */ public MTransitionView replaceBy(ITransitional transView) { return replaceBy(transView, null); } /** * 如果你的动画需要自定义,则需要把自定义的动画在{@link ITransitional}实现后,调用该方法,替换原生的View * NOTE:必须先调用该方法才可以调用below、above方法调整顺序 * * If your Transition needs customization, you need to call this method after the * {@link ITransitional} implementation of the custom view and replace the native View * see the Demo5,6,7 * NOTE: This method must be called before you call the below and above methods to adjust the order * * @param transView 实现自定义动画的View * @param lp LayoutParams只需要设置宽高即可,其他参数都会被忽略(WRAP_CONTENT,MATCH_PATENT都可用);如果该值为null,则默认取被替换的View的宽高 * @return 对应的 {@link MTransitionView}实例 */ public MTransitionView replaceBy(ITransitional transView, @NonNull LayoutParams lp) { if (!(transView instanceof View)) { throw new IllegalArgumentException("transView 必须是View"); } if (mContent.getParent() != null) { ViewGroup parent = ((ViewGroup) mContent.getParent()); parent.removeView(mContent); mContent = (View) transView; if (lp != null) { parent.addView(mContent, new LayoutParams(lp.width, lp.height)); } else { int width = mSourceView.getMeasuredWidth(); int height = mSourceView.getMeasuredHeight(); parent.addView(mContent, new LayoutParams(width, height)); } if (mParentLocation != null) { setParentLocation(mParentLocation); } } return this; } /** * 默认情况下,动画的元素是通过重新绘制一遍,让View在动画中展示 * 但是存在一些特殊情况,重新绘制会没有效果,这时可以尝试调用这个方法,设置为true * 该方法让动画元素不是直接绘制出来,而是绘制到一张Bitmap上,再用Bitmap绘制出来 * * @param b 是否需要用Bitmap绘制 * @return */ public MTransitionView setUseBitmap(boolean b) { if (mContent instanceof CloneView) { ((CloneView) mContent).setUseBitmap(b); } return this; } /** * 设置旋转或者放大的中心点 * @see View#setPivotX(float) */ public MTransitionView setPivotX(float pivotX) { mContent.setPivotX(pivotX); return this; } /** * 设置旋转或者放大的中心点 * @see View#setPivotY(float) */ public MTransitionView setPivotY(float pivotY) { mContent.setPivotY(pivotY); return this; } /** * 返回对应的View * @return */ public View getSourceView() { return mSourceView; } View getContentView() { return mContent; } void setParentLocation(int[] parentLocation) { mParentLocation = parentLocation; mInitTransX = mLocation[0]; mInitTransY = mLocation[1] - mParentLocation[1]; mContent.setTranslationX(mInitTransX); mContent.setTranslationY(mInitTransY); } void contentHasChanged() { if (mContent instanceof CloneView) { ((CloneView) mContent).hasChanged(); } } /** * @see #transitTo(MTransitionView, boolean) */ public MTransitionView transitTo(MTransitionView view) { return transitTo(view, true); } /** * 以 view 作为目标,按照它的位置和大小,进行位移动画和缩放动画(只会按照宽度等比缩放) * * @param view 动画的目标View * @param changSize 是否要做缩放动画,缩放到view对应的大小 * @return */ public MTransitionView transitTo(MTransitionView view, boolean changSize) { mTargetView = view; mTargetView.mIsTarget = true; mChangeSize = changSize; translateTo(view); if (changSize) { changSizeTo(view); } return this; } /** * 以 view 作为目标,按照它的位置,进行位移动画 * * @param view 动画的目标View * @return */ public MTransitionView translateTo(MTransitionView view) { translateXTo(mTargetView.mLocation[0] - mLocation[0]); translateYTo(mTargetView.mLocation[1] - mLocation[1]); return this; } /** * 以 view 作为目标,按照它的大小,进行缩放动画,但只会按照宽度等比缩放 * * @param view 动画的目标View * @return */ public MTransitionView changSizeTo(MTransitionView view) { int targetWidth = 0; if (view.getSourceView() != null) { targetWidth = view.getSourceView().getWidth(); } else { targetWidth = view.getContentView().getWidth(); } int selfWidth = 0; if (getSourceView() != null) { selfWidth = getSourceView().getWidth(); } else { selfWidth = getContentView().getWidth(); } if (targetWidth != 0 && selfWidth != 0) { setPivotX(0); setPivotY(0); float scale = (float) targetWidth / selfWidth; scaleXTo(scale); scaleYTo(scale); } return this; } void setVisibility(int visibility) { mContent.setVisibility(visibility); } void updateLocation() { if (getSourceView() != null) { getSourceView().getLocationInWindow(mLocation); mContent.setScrollX(getSourceView().getScrollX()); mContent.setScrollY(getSourceView().getScrollY()); } if (mParentLocation != null) { setParentLocation(mParentLocation); } } /** * 设置动画View的背景颜色,在某些情况下,调用这个方法可以让动画更加完美 * NOTE:默认是白色的 * * @param color * @return */ public MTransitionView setBgColor(int color) { if (mContent instanceof CloneView) { ((CloneView) mContent).setBgColor(color); } // mContent.setBackgroundColor(color); return this; } // ----------------------------------- 动画元素 start ---------------------------------- /** * 设置透明度动画 * * @param from 取值范围[0, 1] * @param to 取值范围[0, 1] * @return */ public MTransitionView alpha(float from, float to) { mTransition.alphaFrom(from); mTransition.alphaTo(to); return this; } /** * @see #alpha(float, float) */ public MTransitionView alphaFrom(float from) { mTransition.alphaFrom(from); return this; } /** * @see #alpha(float, float) */ public MTransitionView alphaTo(float to) { mTransition.alphaTo(to); return this; } /** * 设置 {@link #alpha(float, float)} 动画的时长 * * @param duration 动画时长 * @return */ public MTransitionView alphaDuration(int duration) { mTransition.alphaDuration(duration); return this; } /** * 设置 {@link #alpha(float, float)} 动画的延时启动时间 * * @param delay 动画的延时启动时间 * @return */ public MTransitionView alphaStartDelay(int delay) { mTransition.alphaStartDelay(delay); return this; } /** * 设置 {@link #alpha(float, float)} 动画的差值器 * * @param interpolator 动画差值器 * @return */ public MTransitionView alphaInterpolator(Interpolator interpolator) { mTransition.alphaInterpolator(interpolator); return this; } /** * 设置X轴位移动画 * * @param from 动画开始时的X值 * @param to 动画结束时的X值 * @return */ public MTransitionView translateX(int from, int to) { mTransition.translateXFrom(from); mTransition.translateXTo(to); return this; } /** * @see #translateX(int, int) */ public MTransitionView translateXFrom(int from) { mTransition.translateXFrom(from); return this; } /** * @see #translateX(int, int) */ public MTransitionView translateXTo(int to) { mTransition.translateXTo(to); return this; } /** * 设置 {@link #translateX(int, int)} 动画的时长 * * @param duration 动画时长 * @return */ public MTransitionView translateXDuration(int duration) { mTransition.translateXDuration(duration); return this; } /** * 设置 {@link #translateX(int, int)} 动画的延时启动时间 * * @param delay 动画的延时启动时间 * @return */ public MTransitionView translateXStartDelay(int delay) { mTransition.translateXStartDelay(delay); return this; } /** * 设置 {@link #translateX(int, int)} 动画的差值器 * * @param interpolator 动画差值器 * @return */ public MTransitionView translateXInterpolator(Interpolator interpolator) { mTransition.translateXInterpolator(interpolator); return this; } /** * 设置Y轴位移动画 * * @param from 动画开始时的Y值 * @param to 动画结束时的Y值 * @return */ public MTransitionView translateY(int from, int to) { mTransition.translateYFrom(from); mTransition.translateYTo(to); return this; } /** * @see #translateY(int, int) */ public MTransitionView translateYFrom(int from) { mTransition.translateYFrom(from); return this; } /** * @see #translateY(int, int) */ public MTransitionView translateYTo(int to) { mTransition.translateYTo(to); return this; } /** * 设置 {@link #translateY(int, int)} 动画的时长 * * @param duration 动画时长 * @return */ public MTransitionView translateYDuration(int duration) { mTransition.translateYDuration(duration); return this; } /** * 设置 {@link #translateY(int, int)} 动画的延时启动时间 * * @param delay 动画的延时启动时间 * @return */ public MTransitionView translateYStartDelay(int delay) { mTransition.translateYStartDelay(delay); return this; } /** * 设置 {@link #translateY(int, int)} 动画的差值器 * * @param interpolator 动画差值器 * @return */ public MTransitionView translateYInterpolator(Interpolator interpolator) { mTransition.translateYInterpolator(interpolator); return this; } /** * 设置X轴的缩放动画 * * @param from 取值范围[0, 1] * @param to 取值范围[0, 1] * @return */ public MTransitionView scaleX(float from, float to) { mTransition.scaleXFrom(from); mTransition.scaleXTo(to); return this; } /** * @see #scaleX(float, float) */ public MTransitionView scaleXFrom(float from) { mTransition.scaleXFrom(from); return this; } /** * @see #scaleX(float, float) */ public MTransitionView scaleXTo(float to) { mTransition.scaleXTo(to); return this; } /** * 设置 {@link #scaleX(float, float)} 动画的时长 * * @param duration 动画时长 * @return */ public MTransitionView scaleXDuration(int duration) { mTransition.scaleXDuration(duration); return this; } /** * 设置 {@link #scaleX(float, float)} 动画的延时启动时间 * * @param delay 动画的延时启动时间 * @return */ public MTransitionView scaleXStartDelay(int delay) { mTransition.scaleXStartDelay(delay); return this; } /** * 设置 {@link #scaleX(float, float)} 动画的差值器 * * @param interpolator 动画差值器 * @return */ public MTransitionView scaleXInterpolator(Interpolator interpolator) { mTransition.scaleXInterpolator(interpolator); return this; } /** * 设置Y轴的缩放动画 * * @param from 取值范围[0, 1] * @param to 取值范围[0, 1] * @return */ public MTransitionView scaleY(float from, float to) { mTransition.scaleYFrom(from); mTransition.scaleYTo(to); return this; } /** * @see #scaleY(float, float) */ public MTransitionView scaleYFrom(float from) { mTransition.scaleYFrom(from); return this; } /** * @see #scaleY(float, float) */ public MTransitionView scaleYTo(float to) { mTransition.scaleYTo(to); return this; } /** * 设置 {@link #scaleY(float, float)} 动画的时长 * * @param duration 动画时长 * @return */ public MTransitionView scaleYDuration(int duration) { mTransition.scaleYDuration(duration); return this; } /** * 设置 {@link #scaleY(float, float)} 动画的延时启动时间 * * @param delay 动画的延时启动时间 * @return */ public MTransitionView scaleYStartDelay(int delay) { mTransition.scaleYStartDelay(delay); return this; } /** * 设置 {@link #scaleY(float, float)} 动画的差值器 * * @param interpolator 动画差值器 * @return */ public MTransitionView scaleYInterpolator(Interpolator interpolator) { mTransition.scaleYInterpolator(interpolator); return this; } /** * 设置X轴的旋转动画 * * @param from * @param to * @return */ public MTransitionView rotateX(int from, int to) { mTransition.rotateXFrom(from); mTransition.rotateXTo(to); return this; } /** * @see #rotateX(int, int) */ public MTransitionView rotateXFrom(int from) { mTransition.rotateXFrom(from); return this; } /** * @see #rotateX(int, int) */ public MTransitionView rotateXTo(int to) { mTransition.rotateXTo(to); return this; } /** * 设置 {@link #rotateX(int, int)} 动画的时长 * * @param duration 动画时长 * @return */ public MTransitionView rotateXDuration(int duration) { mTransition.rotateXDuration(duration); return this; } /** * 设置 {@link #rotateX(int, int)} 动画的延时启动时间 * * @param delay 动画的延时启动时间 * @return */ public MTransitionView rotateXStartDelay(int delay) { mTransition.rotateXStartDelay(delay); return this; } /** * 设置 {@link #rotateX(int, int)} 动画的差值器 * * @param interpolator 动画差值器 * @return */ public MTransitionView rotateXInterpolator(Interpolator interpolator) { mTransition.rotateXInterpolator(interpolator); return this; } /** * 设置Y轴的旋转动画 * * @param from * @param to * @return */ public MTransitionView rotateY(int from, int to) { mTransition.rotateYFrom(from); mTransition.rotateYTo(to); return this; } /** * @see #rotateY(int, int) */ public MTransitionView rotateYFrom(int from) { mTransition.rotateYFrom(from); return this; } /** * @see #rotateY(int, int) */ public MTransitionView rotateYTo(int to) { mTransition.rotateYTo(to); return this; } /** * 设置 {@link #rotateY(int, int)} 动画的时长 * * @param duration 动画时长 * @return */ public MTransitionView rotateYDuration(int duration) { mTransition.rotateYDuration(duration); return this; } /** * 设置 {@link #rotateY(int, int)} 动画的延时启动时间 * * @param delay 动画的延时启动时间 * @return */ public MTransitionView rotateYStartDelay(int delay) { mTransition.rotateYStartDelay(delay); return this; } /** * 设置 {@link #rotateY(int, int)} 动画的差值器 * * @param interpolator 动画差值器 * @return */ public MTransitionView rotateYInterpolator(Interpolator interpolator) { mTransition.rotateYInterpolator(interpolator); return this; } /** * 设置Z轴的旋转动画 * * @param from * @param to * @return */ public MTransitionView rotate(int from, int to) { mTransition.rotateZFrom(from); mTransition.rotateZTo(to); return this; } /** * @see #rotate(int, int) */ public MTransitionView rotateFrom(int from) { mTransition.rotateZFrom(from); return this; } /** * @see #rotate(int, int) */ public MTransitionView rotateTo(int to) { mTransition.rotateZTo(to); return this; } /** * 设置 {@link #rotate(int, int)} 动画的时长 * * @param duration 动画时长 * @return */ public MTransitionView rotateDuration(int duration) { mTransition.rotateZDuration(duration); return this; } /** * 设置 {@link #rotate(int, int)} 动画的延时启动时间 * * @param delay 动画的延时启动时间 * @return */ public MTransitionView rotateStartDelay(int delay) { mTransition.rotateZStartDelay(delay); return this; } /** * 设置 {@link #rotate(int, int)} 动画的差值器 * * @param interpolator 动画差值器 * @return */ public MTransitionView rotateInterpolator(Interpolator interpolator) { mTransition.rotateZInterpolator(interpolator); return this; } // ----------------------------------- 动画元素 end ---------------------------------- /** * 设置该动画元素深度层次顺序,置于target的上层 * * @param target 基准动画元素 * @return */ public MTransitionView above(@NonNull MTransitionView target) { if (mContent.getParent() != null) { ((ViewGroup) mContent.getParent()).removeView(mContent); } target.getBelongPage().aboveOn(this, target); return this; } /** * 设置该动画元素深度层次顺序,置于target的下层 * * @param target 基准动画元素 * @return */ public MTransitionView below(@NonNull MTransitionView target) { if (mContent.getParent() != null) { ((ViewGroup) mContent.getParent()).removeView(mContent); } target.getBelongPage().belowTo(this, target); return this; } void setBelongPage(MTransitionPage mBelongPage) { this.mBelongPage = mBelongPage; } /** * 获取包含该实例的MTransitionPage * * @return 包含该实例的MTransitionPage实例 */ public @NonNull MTransitionPage getBelongPage() { return mBelongPage; } public MTransitionView setDuration(long duration) { return setDuration(duration, true); } MTransitionView setDuration(long duration, boolean byUser) { mTransition.setDuration(duration, byUser); return this; } public MTransitionView setStartDelay(long delay) { mTransition.setStartDelay(delay); return this; } long getMaxAnimTime() { return mTransition.getMaxAnimTime(); } /** * 获取View的屏幕位置信息 * * @return */ public int[] getLocation() { return mLocation; } /** * 让该View在场景切换动画过程中隐藏不显示 */ public void hideDuringTrasition() { alpha(0f, 0f); } /** * 获取该View的宽度 * @return */ public int getWidth() { return getSourceView().getMeasuredWidth(); } /** * 获取该View的高度 * @return */ public int getHeight() { return getSourceView().getMeasuredHeight(); } }