11f8c01181bcdef6e7e7e359ecde003939523b718George Mount/* 21f8c01181bcdef6e7e7e359ecde003939523b718George Mount * Copyright (C) 2014 The Android Open Source Project 31f8c01181bcdef6e7e7e359ecde003939523b718George Mount * 41f8c01181bcdef6e7e7e359ecde003939523b718George Mount * Licensed under the Apache License, Version 2.0 (the "License"); 51f8c01181bcdef6e7e7e359ecde003939523b718George Mount * you may not use this file except in compliance with the License. 61f8c01181bcdef6e7e7e359ecde003939523b718George Mount * You may obtain a copy of the License at 71f8c01181bcdef6e7e7e359ecde003939523b718George Mount * 81f8c01181bcdef6e7e7e359ecde003939523b718George Mount * http://www.apache.org/licenses/LICENSE-2.0 91f8c01181bcdef6e7e7e359ecde003939523b718George Mount * 101f8c01181bcdef6e7e7e359ecde003939523b718George Mount * Unless required by applicable law or agreed to in writing, software 111f8c01181bcdef6e7e7e359ecde003939523b718George Mount * distributed under the License is distributed on an "AS IS" BASIS, 121f8c01181bcdef6e7e7e359ecde003939523b718George Mount * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131f8c01181bcdef6e7e7e359ecde003939523b718George Mount * See the License for the specific language governing permissions and 141f8c01181bcdef6e7e7e359ecde003939523b718George Mount * limitations under the License. 151f8c01181bcdef6e7e7e359ecde003939523b718George Mount */ 161f8c01181bcdef6e7e7e359ecde003939523b718George Mountpackage android.transition; 171f8c01181bcdef6e7e7e359ecde003939523b718George Mount 181f8c01181bcdef6e7e7e359ecde003939523b718George Mountimport com.android.internal.R; 191f8c01181bcdef6e7e7e359ecde003939523b718George Mount 201f8c01181bcdef6e7e7e359ecde003939523b718George Mountimport android.animation.Animator; 211f8c01181bcdef6e7e7e359ecde003939523b718George Mountimport android.animation.AnimatorListenerAdapter; 221f8c01181bcdef6e7e7e359ecde003939523b718George Mountimport android.animation.ObjectAnimator; 231f8c01181bcdef6e7e7e359ecde003939523b718George Mountimport android.animation.TimeInterpolator; 241f8c01181bcdef6e7e7e359ecde003939523b718George Mountimport android.graphics.Path; 25727a6cf6ad06bbb43c0c309c33776394a0012895George Mountimport android.transition.Transition.TransitionListener; 261f8c01181bcdef6e7e7e359ecde003939523b718George Mountimport android.view.View; 271f8c01181bcdef6e7e7e359ecde003939523b718George Mount 281f8c01181bcdef6e7e7e359ecde003939523b718George Mount/** 291f8c01181bcdef6e7e7e359ecde003939523b718George Mount * This class is used by Slide and Explode to create an animator that goes from the start 301f8c01181bcdef6e7e7e359ecde003939523b718George Mount * position to the end position. It takes into account the canceled position so that it 311f8c01181bcdef6e7e7e359ecde003939523b718George Mount * will not blink out or shift suddenly when the transition is interrupted. 321f8c01181bcdef6e7e7e359ecde003939523b718George Mount */ 331f8c01181bcdef6e7e7e359ecde003939523b718George Mountclass TranslationAnimationCreator { 341f8c01181bcdef6e7e7e359ecde003939523b718George Mount 351f8c01181bcdef6e7e7e359ecde003939523b718George Mount /** 361f8c01181bcdef6e7e7e359ecde003939523b718George Mount * Creates an animator that can be used for x and/or y translations. When interrupted, 371f8c01181bcdef6e7e7e359ecde003939523b718George Mount * it sets a tag to keep track of the position so that it may be continued from position. 381f8c01181bcdef6e7e7e359ecde003939523b718George Mount * 391f8c01181bcdef6e7e7e359ecde003939523b718George Mount * @param view The view being moved. This may be in the overlay for onDisappear. 401f8c01181bcdef6e7e7e359ecde003939523b718George Mount * @param values The values containing the view in the view hierarchy. 411f8c01181bcdef6e7e7e359ecde003939523b718George Mount * @param viewPosX The x screen coordinate of view 421f8c01181bcdef6e7e7e359ecde003939523b718George Mount * @param viewPosY The y screen coordinate of view 431f8c01181bcdef6e7e7e359ecde003939523b718George Mount * @param startX The start translation x of view 441f8c01181bcdef6e7e7e359ecde003939523b718George Mount * @param startY The start translation y of view 451f8c01181bcdef6e7e7e359ecde003939523b718George Mount * @param endX The end translation x of view 461f8c01181bcdef6e7e7e359ecde003939523b718George Mount * @param endY The end translation y of view 471f8c01181bcdef6e7e7e359ecde003939523b718George Mount * @param interpolator The interpolator to use with this animator. 481f8c01181bcdef6e7e7e359ecde003939523b718George Mount * @return An animator that moves from (startX, startY) to (endX, endY) unless there was 491f8c01181bcdef6e7e7e359ecde003939523b718George Mount * a previous interruption, in which case it moves from the current position to (endX, endY). 501f8c01181bcdef6e7e7e359ecde003939523b718George Mount */ 511f8c01181bcdef6e7e7e359ecde003939523b718George Mount static Animator createAnimation(View view, TransitionValues values, int viewPosX, int viewPosY, 52727a6cf6ad06bbb43c0c309c33776394a0012895George Mount float startX, float startY, float endX, float endY, TimeInterpolator interpolator, 53727a6cf6ad06bbb43c0c309c33776394a0012895George Mount Transition transition) { 541f8c01181bcdef6e7e7e359ecde003939523b718George Mount float terminalX = view.getTranslationX(); 551f8c01181bcdef6e7e7e359ecde003939523b718George Mount float terminalY = view.getTranslationY(); 561f8c01181bcdef6e7e7e359ecde003939523b718George Mount int[] startPosition = (int[]) values.view.getTag(R.id.transitionPosition); 571f8c01181bcdef6e7e7e359ecde003939523b718George Mount if (startPosition != null) { 581f8c01181bcdef6e7e7e359ecde003939523b718George Mount startX = startPosition[0] - viewPosX + terminalX; 591f8c01181bcdef6e7e7e359ecde003939523b718George Mount startY = startPosition[1] - viewPosY + terminalY; 601f8c01181bcdef6e7e7e359ecde003939523b718George Mount } 611f8c01181bcdef6e7e7e359ecde003939523b718George Mount // Initial position is at translation startX, startY, so position is offset by that amount 621f8c01181bcdef6e7e7e359ecde003939523b718George Mount int startPosX = viewPosX + Math.round(startX - terminalX); 631f8c01181bcdef6e7e7e359ecde003939523b718George Mount int startPosY = viewPosY + Math.round(startY - terminalY); 641f8c01181bcdef6e7e7e359ecde003939523b718George Mount 651f8c01181bcdef6e7e7e359ecde003939523b718George Mount view.setTranslationX(startX); 661f8c01181bcdef6e7e7e359ecde003939523b718George Mount view.setTranslationY(startY); 671f8c01181bcdef6e7e7e359ecde003939523b718George Mount if (startX == endX && startY == endY) { 681f8c01181bcdef6e7e7e359ecde003939523b718George Mount return null; 691f8c01181bcdef6e7e7e359ecde003939523b718George Mount } 701f8c01181bcdef6e7e7e359ecde003939523b718George Mount Path path = new Path(); 711f8c01181bcdef6e7e7e359ecde003939523b718George Mount path.moveTo(startX, startY); 721f8c01181bcdef6e7e7e359ecde003939523b718George Mount path.lineTo(endX, endY); 731f8c01181bcdef6e7e7e359ecde003939523b718George Mount ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, View.TRANSLATION_Y, 741f8c01181bcdef6e7e7e359ecde003939523b718George Mount path); 751f8c01181bcdef6e7e7e359ecde003939523b718George Mount 761f8c01181bcdef6e7e7e359ecde003939523b718George Mount TransitionPositionListener listener = new TransitionPositionListener(view, values.view, 771f8c01181bcdef6e7e7e359ecde003939523b718George Mount startPosX, startPosY, terminalX, terminalY); 78727a6cf6ad06bbb43c0c309c33776394a0012895George Mount transition.addListener(listener); 791f8c01181bcdef6e7e7e359ecde003939523b718George Mount anim.addListener(listener); 801f8c01181bcdef6e7e7e359ecde003939523b718George Mount anim.addPauseListener(listener); 811f8c01181bcdef6e7e7e359ecde003939523b718George Mount anim.setInterpolator(interpolator); 821f8c01181bcdef6e7e7e359ecde003939523b718George Mount return anim; 831f8c01181bcdef6e7e7e359ecde003939523b718George Mount } 841f8c01181bcdef6e7e7e359ecde003939523b718George Mount 85727a6cf6ad06bbb43c0c309c33776394a0012895George Mount private static class TransitionPositionListener extends AnimatorListenerAdapter implements 86727a6cf6ad06bbb43c0c309c33776394a0012895George Mount TransitionListener { 871f8c01181bcdef6e7e7e359ecde003939523b718George Mount 881f8c01181bcdef6e7e7e359ecde003939523b718George Mount private final View mViewInHierarchy; 891f8c01181bcdef6e7e7e359ecde003939523b718George Mount private final View mMovingView; 901f8c01181bcdef6e7e7e359ecde003939523b718George Mount private final int mStartX; 911f8c01181bcdef6e7e7e359ecde003939523b718George Mount private final int mStartY; 921f8c01181bcdef6e7e7e359ecde003939523b718George Mount private int[] mTransitionPosition; 931f8c01181bcdef6e7e7e359ecde003939523b718George Mount private float mPausedX; 941f8c01181bcdef6e7e7e359ecde003939523b718George Mount private float mPausedY; 951f8c01181bcdef6e7e7e359ecde003939523b718George Mount private final float mTerminalX; 961f8c01181bcdef6e7e7e359ecde003939523b718George Mount private final float mTerminalY; 971f8c01181bcdef6e7e7e359ecde003939523b718George Mount 981f8c01181bcdef6e7e7e359ecde003939523b718George Mount private TransitionPositionListener(View movingView, View viewInHierarchy, 991f8c01181bcdef6e7e7e359ecde003939523b718George Mount int startX, int startY, float terminalX, float terminalY) { 1001f8c01181bcdef6e7e7e359ecde003939523b718George Mount mMovingView = movingView; 1011f8c01181bcdef6e7e7e359ecde003939523b718George Mount mViewInHierarchy = viewInHierarchy; 1021f8c01181bcdef6e7e7e359ecde003939523b718George Mount mStartX = startX - Math.round(mMovingView.getTranslationX()); 1031f8c01181bcdef6e7e7e359ecde003939523b718George Mount mStartY = startY - Math.round(mMovingView.getTranslationY()); 1041f8c01181bcdef6e7e7e359ecde003939523b718George Mount mTerminalX = terminalX; 1051f8c01181bcdef6e7e7e359ecde003939523b718George Mount mTerminalY = terminalY; 1061f8c01181bcdef6e7e7e359ecde003939523b718George Mount mTransitionPosition = (int[]) mViewInHierarchy.getTag(R.id.transitionPosition); 1071f8c01181bcdef6e7e7e359ecde003939523b718George Mount if (mTransitionPosition != null) { 1081f8c01181bcdef6e7e7e359ecde003939523b718George Mount mViewInHierarchy.setTagInternal(R.id.transitionPosition, null); 1091f8c01181bcdef6e7e7e359ecde003939523b718George Mount } 1101f8c01181bcdef6e7e7e359ecde003939523b718George Mount } 1111f8c01181bcdef6e7e7e359ecde003939523b718George Mount 1121f8c01181bcdef6e7e7e359ecde003939523b718George Mount @Override 1131f8c01181bcdef6e7e7e359ecde003939523b718George Mount public void onAnimationCancel(Animator animation) { 1141f8c01181bcdef6e7e7e359ecde003939523b718George Mount if (mTransitionPosition == null) { 1151f8c01181bcdef6e7e7e359ecde003939523b718George Mount mTransitionPosition = new int[2]; 1161f8c01181bcdef6e7e7e359ecde003939523b718George Mount } 1171f8c01181bcdef6e7e7e359ecde003939523b718George Mount mTransitionPosition[0] = Math.round(mStartX + mMovingView.getTranslationX()); 1181f8c01181bcdef6e7e7e359ecde003939523b718George Mount mTransitionPosition[1] = Math.round(mStartY + mMovingView.getTranslationY()); 1191f8c01181bcdef6e7e7e359ecde003939523b718George Mount mViewInHierarchy.setTagInternal(R.id.transitionPosition, mTransitionPosition); 1201f8c01181bcdef6e7e7e359ecde003939523b718George Mount } 1211f8c01181bcdef6e7e7e359ecde003939523b718George Mount 1221f8c01181bcdef6e7e7e359ecde003939523b718George Mount @Override 1231f8c01181bcdef6e7e7e359ecde003939523b718George Mount public void onAnimationEnd(Animator animator) { 1241f8c01181bcdef6e7e7e359ecde003939523b718George Mount } 1251f8c01181bcdef6e7e7e359ecde003939523b718George Mount 1261f8c01181bcdef6e7e7e359ecde003939523b718George Mount @Override 1271f8c01181bcdef6e7e7e359ecde003939523b718George Mount public void onAnimationPause(Animator animator) { 1281f8c01181bcdef6e7e7e359ecde003939523b718George Mount mPausedX = mMovingView.getTranslationX(); 1291f8c01181bcdef6e7e7e359ecde003939523b718George Mount mPausedY = mMovingView.getTranslationY(); 1301f8c01181bcdef6e7e7e359ecde003939523b718George Mount mMovingView.setTranslationX(mTerminalX); 1311f8c01181bcdef6e7e7e359ecde003939523b718George Mount mMovingView.setTranslationY(mTerminalY); 1321f8c01181bcdef6e7e7e359ecde003939523b718George Mount } 1331f8c01181bcdef6e7e7e359ecde003939523b718George Mount 1341f8c01181bcdef6e7e7e359ecde003939523b718George Mount @Override 1351f8c01181bcdef6e7e7e359ecde003939523b718George Mount public void onAnimationResume(Animator animator) { 1361f8c01181bcdef6e7e7e359ecde003939523b718George Mount mMovingView.setTranslationX(mPausedX); 1371f8c01181bcdef6e7e7e359ecde003939523b718George Mount mMovingView.setTranslationY(mPausedY); 1381f8c01181bcdef6e7e7e359ecde003939523b718George Mount } 139727a6cf6ad06bbb43c0c309c33776394a0012895George Mount 140727a6cf6ad06bbb43c0c309c33776394a0012895George Mount @Override 141727a6cf6ad06bbb43c0c309c33776394a0012895George Mount public void onTransitionStart(Transition transition) { 142727a6cf6ad06bbb43c0c309c33776394a0012895George Mount } 143727a6cf6ad06bbb43c0c309c33776394a0012895George Mount 144727a6cf6ad06bbb43c0c309c33776394a0012895George Mount @Override 145727a6cf6ad06bbb43c0c309c33776394a0012895George Mount public void onTransitionEnd(Transition transition) { 146727a6cf6ad06bbb43c0c309c33776394a0012895George Mount mMovingView.setTranslationX(mTerminalX); 147727a6cf6ad06bbb43c0c309c33776394a0012895George Mount mMovingView.setTranslationY(mTerminalY); 148727a6cf6ad06bbb43c0c309c33776394a0012895George Mount } 149727a6cf6ad06bbb43c0c309c33776394a0012895George Mount 150727a6cf6ad06bbb43c0c309c33776394a0012895George Mount @Override 151727a6cf6ad06bbb43c0c309c33776394a0012895George Mount public void onTransitionCancel(Transition transition) { 152727a6cf6ad06bbb43c0c309c33776394a0012895George Mount } 153727a6cf6ad06bbb43c0c309c33776394a0012895George Mount 154727a6cf6ad06bbb43c0c309c33776394a0012895George Mount @Override 155727a6cf6ad06bbb43c0c309c33776394a0012895George Mount public void onTransitionPause(Transition transition) { 156727a6cf6ad06bbb43c0c309c33776394a0012895George Mount } 157727a6cf6ad06bbb43c0c309c33776394a0012895George Mount 158727a6cf6ad06bbb43c0c309c33776394a0012895George Mount @Override 159727a6cf6ad06bbb43c0c309c33776394a0012895George Mount public void onTransitionResume(Transition transition) { 160727a6cf6ad06bbb43c0c309c33776394a0012895George Mount } 1611f8c01181bcdef6e7e7e359ecde003939523b718George Mount } 1621f8c01181bcdef6e7e7e359ecde003939523b718George Mount 1631f8c01181bcdef6e7e7e359ecde003939523b718George Mount} 164