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