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