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 android.graphics.Rect; 19 import android.view.View; 20 import android.view.ViewGroup; 21 22 /** 23 * A propagation that varies with the distance to the epicenter of the Transition 24 * or center of the scene if no epicenter exists. When a View is visible in the 25 * start of the transition, Views farther from the epicenter will transition 26 * sooner than Views closer to the epicenter. When a View is not in the start 27 * of the transition or is not visible at the start of the transition, it will 28 * transition sooner when closer to the epicenter and later when farther from 29 * the epicenter. This is the default TransitionPropagation used with 30 * {@link android.transition.Explode}. 31 */ 32 public class CircularPropagation extends VisibilityPropagation { 33 private static final String TAG = "CircularPropagation"; 34 35 private float mPropagationSpeed = 3.0f; 36 37 /** 38 * Sets the speed at which transition propagation happens, relative to the duration of the 39 * Transition. A <code>propagationSpeed</code> of 1 means that a View centered farthest from 40 * the epicenter and View centered at the epicenter will have a difference 41 * in start delay of approximately the duration of the Transition. A speed of 2 means the 42 * start delay difference will be approximately half of the duration of the transition. A 43 * value of 0 is illegal, but negative values will invert the propagation. 44 * 45 * @param propagationSpeed The speed at which propagation occurs, relative to the duration 46 * of the transition. A speed of 4 means it works 4 times as fast 47 * as the duration of the transition. May not be 0. 48 */ setPropagationSpeed(float propagationSpeed)49 public void setPropagationSpeed(float propagationSpeed) { 50 if (propagationSpeed == 0) { 51 throw new IllegalArgumentException("propagationSpeed may not be 0"); 52 } 53 mPropagationSpeed = propagationSpeed; 54 } 55 56 @Override getStartDelay(ViewGroup sceneRoot, Transition transition, TransitionValues startValues, TransitionValues endValues)57 public long getStartDelay(ViewGroup sceneRoot, Transition transition, 58 TransitionValues startValues, TransitionValues endValues) { 59 if (startValues == null && endValues == null) { 60 return 0; 61 } 62 int directionMultiplier = 1; 63 TransitionValues positionValues; 64 if (endValues == null || getViewVisibility(startValues) == View.VISIBLE) { 65 positionValues = startValues; 66 directionMultiplier = -1; 67 } else { 68 positionValues = endValues; 69 } 70 71 int viewCenterX = getViewX(positionValues); 72 int viewCenterY = getViewY(positionValues); 73 74 Rect epicenter = transition.getEpicenter(); 75 int epicenterX; 76 int epicenterY; 77 if (epicenter != null) { 78 epicenterX = epicenter.centerX(); 79 epicenterY = epicenter.centerY(); 80 } else { 81 int[] loc = new int[2]; 82 sceneRoot.getLocationOnScreen(loc); 83 epicenterX = Math.round(loc[0] + (sceneRoot.getWidth() / 2) 84 + sceneRoot.getTranslationX()); 85 epicenterY = Math.round(loc[1] + (sceneRoot.getHeight() / 2) 86 + sceneRoot.getTranslationY()); 87 } 88 double distance = distance(viewCenterX, viewCenterY, epicenterX, epicenterY); 89 double maxDistance = distance(0, 0, sceneRoot.getWidth(), sceneRoot.getHeight()); 90 double distanceFraction = distance/maxDistance; 91 92 long duration = transition.getDuration(); 93 if (duration < 0) { 94 duration = 300; 95 } 96 97 return Math.round(duration * directionMultiplier / mPropagationSpeed * distanceFraction); 98 } 99 distance(float x1, float y1, float x2, float y2)100 private static double distance(float x1, float y1, float x2, float y2) { 101 double x = x2 - x1; 102 double y = y2 - y1; 103 return Math.hypot(x, y); 104 } 105 } 106