Home | History | Annotate | Download | only in transition
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package android.transition;
     17 
     18 import com.android.internal.R;
     19 
     20 import android.animation.Animator;
     21 import android.animation.AnimatorListenerAdapter;
     22 import android.animation.ObjectAnimator;
     23 import android.animation.TimeInterpolator;
     24 import android.graphics.Path;
     25 import android.view.View;
     26 
     27 /**
     28  * This class is used by Slide and Explode to create an animator that goes from the start
     29  * position to the end position. It takes into account the canceled position so that it
     30  * will not blink out or shift suddenly when the transition is interrupted.
     31  */
     32 class TranslationAnimationCreator {
     33 
     34     /**
     35      * Creates an animator that can be used for x and/or y translations. When interrupted,
     36      * it sets a tag to keep track of the position so that it may be continued from position.
     37      *
     38      * @param view The view being moved. This may be in the overlay for onDisappear.
     39      * @param values The values containing the view in the view hierarchy.
     40      * @param viewPosX The x screen coordinate of view
     41      * @param viewPosY The y screen coordinate of view
     42      * @param startX The start translation x of view
     43      * @param startY The start translation y of view
     44      * @param endX The end translation x of view
     45      * @param endY The end translation y of view
     46      * @param interpolator The interpolator to use with this animator.
     47      * @return An animator that moves from (startX, startY) to (endX, endY) unless there was
     48      * a previous interruption, in which case it moves from the current position to (endX, endY).
     49      */
     50     static Animator createAnimation(View view, TransitionValues values, int viewPosX, int viewPosY,
     51             float startX, float startY, float endX, float endY, TimeInterpolator interpolator) {
     52         float terminalX = view.getTranslationX();
     53         float terminalY = view.getTranslationY();
     54         int[] startPosition = (int[]) values.view.getTag(R.id.transitionPosition);
     55         if (startPosition != null) {
     56             startX = startPosition[0] - viewPosX + terminalX;
     57             startY = startPosition[1] - viewPosY + terminalY;
     58         }
     59         // Initial position is at translation startX, startY, so position is offset by that amount
     60         int startPosX = viewPosX + Math.round(startX - terminalX);
     61         int startPosY = viewPosY + Math.round(startY - terminalY);
     62 
     63         view.setTranslationX(startX);
     64         view.setTranslationY(startY);
     65         if (startX == endX && startY == endY) {
     66             return null;
     67         }
     68         Path path = new Path();
     69         path.moveTo(startX, startY);
     70         path.lineTo(endX, endY);
     71         ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, View.TRANSLATION_Y,
     72                 path);
     73 
     74         TransitionPositionListener listener = new TransitionPositionListener(view, values.view,
     75                 startPosX, startPosY, terminalX, terminalY);
     76         anim.addListener(listener);
     77         anim.addPauseListener(listener);
     78         anim.setInterpolator(interpolator);
     79         return anim;
     80     }
     81 
     82     private static class TransitionPositionListener extends AnimatorListenerAdapter {
     83 
     84         private final View mViewInHierarchy;
     85         private final View mMovingView;
     86         private final int mStartX;
     87         private final int mStartY;
     88         private int[] mTransitionPosition;
     89         private float mPausedX;
     90         private float mPausedY;
     91         private final float mTerminalX;
     92         private final float mTerminalY;
     93 
     94         private TransitionPositionListener(View movingView, View viewInHierarchy,
     95                 int startX, int startY, float terminalX, float terminalY) {
     96             mMovingView = movingView;
     97             mViewInHierarchy = viewInHierarchy;
     98             mStartX = startX - Math.round(mMovingView.getTranslationX());
     99             mStartY = startY - Math.round(mMovingView.getTranslationY());
    100             mTerminalX = terminalX;
    101             mTerminalY = terminalY;
    102             mTransitionPosition = (int[]) mViewInHierarchy.getTag(R.id.transitionPosition);
    103             if (mTransitionPosition != null) {
    104                 mViewInHierarchy.setTagInternal(R.id.transitionPosition, null);
    105             }
    106         }
    107 
    108         @Override
    109         public void onAnimationCancel(Animator animation) {
    110             if (mTransitionPosition == null) {
    111                 mTransitionPosition = new int[2];
    112             }
    113             mTransitionPosition[0] = Math.round(mStartX + mMovingView.getTranslationX());
    114             mTransitionPosition[1] = Math.round(mStartY + mMovingView.getTranslationY());
    115             mViewInHierarchy.setTagInternal(R.id.transitionPosition, mTransitionPosition);
    116         }
    117 
    118         @Override
    119         public void onAnimationEnd(Animator animator) {
    120             mMovingView.setTranslationX(mTerminalX);
    121             mMovingView.setTranslationY(mTerminalY);
    122         }
    123 
    124         @Override
    125         public void onAnimationPause(Animator animator) {
    126             mPausedX = mMovingView.getTranslationX();
    127             mPausedY = mMovingView.getTranslationY();
    128             mMovingView.setTranslationX(mTerminalX);
    129             mMovingView.setTranslationY(mTerminalY);
    130         }
    131 
    132         @Override
    133         public void onAnimationResume(Animator animator) {
    134             mMovingView.setTranslationX(mPausedX);
    135             mMovingView.setTranslationY(mPausedY);
    136         }
    137     }
    138 
    139 }
    140