1 package androidx.leanback.transition; 2 3 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 4 5 import android.animation.Animator; 6 import android.animation.AnimatorListenerAdapter; 7 import android.animation.ObjectAnimator; 8 import android.animation.TimeInterpolator; 9 import android.graphics.Path; 10 import android.transition.Transition; 11 import android.transition.Transition.TransitionListener; 12 import android.transition.TransitionValues; 13 import android.view.View; 14 15 import androidx.annotation.RequiresApi; 16 import androidx.annotation.RestrictTo; 17 import androidx.leanback.R; 18 19 /** 20 * This class is used by Slide and Explode to create an animator that goes from the start 21 * position to the end position. It takes into account the canceled position so that it 22 * will not blink out or shift suddenly when the transition is interrupted. 23 * @hide 24 */ 25 @RequiresApi(21) 26 @RestrictTo(LIBRARY_GROUP) 27 class TranslationAnimationCreator { 28 29 /** 30 * Creates an animator that can be used for x and/or y translations. When interrupted, 31 * it sets a tag to keep track of the position so that it may be continued from position. 32 * 33 * @param view The view being moved. This may be in the overlay for onDisappear. 34 * @param values The values containing the view in the view hierarchy. 35 * @param viewPosX The x screen coordinate of view 36 * @param viewPosY The y screen coordinate of view 37 * @param startX The start translation x of view 38 * @param startY The start translation y of view 39 * @param endX The end translation x of view 40 * @param endY The end translation y of view 41 * @param interpolator The interpolator to use with this animator. 42 * @return An animator that moves from (startX, startY) to (endX, endY) unless there was 43 * a previous interruption, in which case it moves from the current position to (endX, endY). 44 */ createAnimation(View view, TransitionValues values, int viewPosX, int viewPosY, float startX, float startY, float endX, float endY, TimeInterpolator interpolator, Transition transition)45 static Animator createAnimation(View view, TransitionValues values, int viewPosX, int viewPosY, 46 float startX, float startY, float endX, float endY, TimeInterpolator interpolator, 47 Transition transition) { 48 float terminalX = view.getTranslationX(); 49 float terminalY = view.getTranslationY(); 50 int[] startPosition = (int[]) values.view.getTag(R.id.transitionPosition); 51 if (startPosition != null) { 52 startX = startPosition[0] - viewPosX + terminalX; 53 startY = startPosition[1] - viewPosY + terminalY; 54 } 55 // Initial position is at translation startX, startY, so position is offset by that amount 56 int startPosX = viewPosX + Math.round(startX - terminalX); 57 int startPosY = viewPosY + Math.round(startY - terminalY); 58 59 view.setTranslationX(startX); 60 view.setTranslationY(startY); 61 if (startX == endX && startY == endY) { 62 return null; 63 } 64 Path path = new Path(); 65 path.moveTo(startX, startY); 66 path.lineTo(endX, endY); 67 ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, View.TRANSLATION_Y, 68 path); 69 70 TransitionPositionListener listener = new TransitionPositionListener(view, values.view, 71 startPosX, startPosY, terminalX, terminalY); 72 transition.addListener(listener); 73 anim.addListener(listener); 74 anim.addPauseListener(listener); 75 anim.setInterpolator(interpolator); 76 return anim; 77 } 78 79 private static class TransitionPositionListener extends AnimatorListenerAdapter implements 80 TransitionListener { 81 82 private final View mViewInHierarchy; 83 private final View mMovingView; 84 private final int mStartX; 85 private final int mStartY; 86 private int[] mTransitionPosition; 87 private float mPausedX; 88 private float mPausedY; 89 private final float mTerminalX; 90 private final float mTerminalY; 91 TransitionPositionListener(View movingView, View viewInHierarchy, int startX, int startY, float terminalX, float terminalY)92 TransitionPositionListener(View movingView, View viewInHierarchy, 93 int startX, int startY, float terminalX, float terminalY) { 94 mMovingView = movingView; 95 mViewInHierarchy = viewInHierarchy; 96 mStartX = startX - Math.round(mMovingView.getTranslationX()); 97 mStartY = startY - Math.round(mMovingView.getTranslationY()); 98 mTerminalX = terminalX; 99 mTerminalY = terminalY; 100 mTransitionPosition = (int[]) mViewInHierarchy.getTag(R.id.transitionPosition); 101 if (mTransitionPosition != null) { 102 mViewInHierarchy.setTag(R.id.transitionPosition, null); 103 } 104 } 105 106 @Override onAnimationCancel(Animator animation)107 public void onAnimationCancel(Animator animation) { 108 if (mTransitionPosition == null) { 109 mTransitionPosition = new int[2]; 110 } 111 mTransitionPosition[0] = Math.round(mStartX + mMovingView.getTranslationX()); 112 mTransitionPosition[1] = Math.round(mStartY + mMovingView.getTranslationY()); 113 mViewInHierarchy.setTag(R.id.transitionPosition, mTransitionPosition); 114 } 115 116 @Override onAnimationEnd(Animator animator)117 public void onAnimationEnd(Animator animator) { 118 } 119 120 @Override onAnimationPause(Animator animator)121 public void onAnimationPause(Animator animator) { 122 mPausedX = mMovingView.getTranslationX(); 123 mPausedY = mMovingView.getTranslationY(); 124 mMovingView.setTranslationX(mTerminalX); 125 mMovingView.setTranslationY(mTerminalY); 126 } 127 128 @Override onAnimationResume(Animator animator)129 public void onAnimationResume(Animator animator) { 130 mMovingView.setTranslationX(mPausedX); 131 mMovingView.setTranslationY(mPausedY); 132 } 133 134 @Override onTransitionStart(Transition transition)135 public void onTransitionStart(Transition transition) { 136 } 137 138 @Override onTransitionEnd(Transition transition)139 public void onTransitionEnd(Transition transition) { 140 mMovingView.setTranslationX(mTerminalX); 141 mMovingView.setTranslationY(mTerminalY); 142 } 143 144 @Override onTransitionCancel(Transition transition)145 public void onTransitionCancel(Transition transition) { 146 } 147 148 @Override onTransitionPause(Transition transition)149 public void onTransitionPause(Transition transition) { 150 } 151 152 @Override onTransitionResume(Transition transition)153 public void onTransitionResume(Transition transition) { 154 } 155 } 156 TranslationAnimationCreator()157 private TranslationAnimationCreator() { 158 } 159 } 160