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