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