summaryrefslogtreecommitdiff
path: root/android/transition/TransitionSet.java
diff options
context:
space:
mode:
authorJustin Klaassen <justinklaassen@google.com>2017-09-15 17:58:39 -0400
committerJustin Klaassen <justinklaassen@google.com>2017-09-15 17:58:39 -0400
commit10d07c88d69cc64f73a069163e7ea5ba2519a099 (patch)
tree8dbd149eb350320a29c3d10e7ad3201de1c5cbee /android/transition/TransitionSet.java
parent677516fb6b6f207d373984757d3d9450474b6b00 (diff)
downloadandroid-28-10d07c88d69cc64f73a069163e7ea5ba2519a099.tar.gz
Import Android SDK Platform PI [4335822]
/google/data/ro/projects/android/fetch_artifact \ --bid 4335822 \ --target sdk_phone_armv7-win_sdk \ sdk-repo-linux-sources-4335822.zip AndroidVersion.ApiLevel has been modified to appear as 28 Change-Id: Ic8f04be005a71c2b9abeaac754d8da8d6f9a2c32
Diffstat (limited to 'android/transition/TransitionSet.java')
-rw-r--r--android/transition/TransitionSet.java567
1 files changed, 567 insertions, 0 deletions
diff --git a/android/transition/TransitionSet.java b/android/transition/TransitionSet.java
new file mode 100644
index 00000000..a41fe64d
--- /dev/null
+++ b/android/transition/TransitionSet.java
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.transition;
+
+import android.animation.TimeInterpolator;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AndroidRuntimeException;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.internal.R;
+
+import java.util.ArrayList;
+
+/**
+ * A TransitionSet is a parent of child transitions (including other
+ * TransitionSets). Using TransitionSets enables more complex
+ * choreography of transitions, where some sets play {@link #ORDERING_TOGETHER} and
+ * others play {@link #ORDERING_SEQUENTIAL}. For example, {@link AutoTransition}
+ * uses a TransitionSet to sequentially play a Fade(Fade.OUT), followed by
+ * a {@link ChangeBounds}, followed by a Fade(Fade.OUT) transition.
+ *
+ * <p>A TransitionSet can be described in a resource file by using the
+ * tag <code>transitionSet</code>, along with the standard
+ * attributes of {@link android.R.styleable#TransitionSet} and
+ * {@link android.R.styleable#Transition}. Child transitions of the
+ * TransitionSet object can be loaded by adding those child tags inside the
+ * enclosing <code>transitionSet</code> tag. For example, the following xml
+ * describes a TransitionSet that plays a Fade and then a ChangeBounds
+ * transition on the affected view targets:</p>
+ * <pre>
+ * &lt;transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
+ * android:transitionOrdering="sequential"&gt;
+ * &lt;fade/&gt;
+ * &lt;changeBounds/&gt;
+ * &lt;/transitionSet&gt;
+ * </pre>
+ */
+public class TransitionSet extends Transition {
+
+ ArrayList<Transition> mTransitions = new ArrayList<Transition>();
+ private boolean mPlayTogether = true;
+ int mCurrentListeners;
+ boolean mStarted = false;
+
+ /**
+ * A flag used to indicate that the child transitions of this set
+ * should all start at the same time.
+ */
+ public static final int ORDERING_TOGETHER = 0;
+ /**
+ * A flag used to indicate that the child transitions of this set should
+ * play in sequence; when one child transition ends, the next child
+ * transition begins. Note that a transition does not end until all
+ * instances of it (which are playing on all applicable targets of the
+ * transition) end.
+ */
+ public static final int ORDERING_SEQUENTIAL = 1;
+
+ /**
+ * Constructs an empty transition set. Add child transitions to the
+ * set by calling {@link #addTransition(Transition)} )}. By default,
+ * child transitions will play {@link #ORDERING_TOGETHER together}.
+ */
+ public TransitionSet() {
+ }
+
+ public TransitionSet(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TransitionSet);
+ int ordering = a.getInt(R.styleable.TransitionSet_transitionOrdering,
+ TransitionSet.ORDERING_TOGETHER);
+ setOrdering(ordering);
+ a.recycle();
+ }
+
+ /**
+ * Sets the play order of this set's child transitions.
+ *
+ * @param ordering {@link #ORDERING_TOGETHER} to play this set's child
+ * transitions together, {@link #ORDERING_SEQUENTIAL} to play the child
+ * transitions in sequence.
+ * @return This transitionSet object.
+ */
+ public TransitionSet setOrdering(int ordering) {
+ switch (ordering) {
+ case ORDERING_SEQUENTIAL:
+ mPlayTogether = false;
+ break;
+ case ORDERING_TOGETHER:
+ mPlayTogether = true;
+ break;
+ default:
+ throw new AndroidRuntimeException("Invalid parameter for TransitionSet " +
+ "ordering: " + ordering);
+ }
+ return this;
+ }
+
+ /**
+ * Returns the ordering of this TransitionSet. By default, the value is
+ * {@link #ORDERING_TOGETHER}.
+ *
+ * @return {@link #ORDERING_TOGETHER} if child transitions will play at the same
+ * time, {@link #ORDERING_SEQUENTIAL} if they will play in sequence.
+ *
+ * @see #setOrdering(int)
+ */
+ public int getOrdering() {
+ return mPlayTogether ? ORDERING_TOGETHER : ORDERING_SEQUENTIAL;
+ }
+
+ /**
+ * Adds child transition to this set. The order in which this child transition
+ * is added relative to other child transitions that are added, in addition to
+ * the {@link #getOrdering() ordering} property, determines the
+ * order in which the transitions are started.
+ *
+ * <p>If this transitionSet has a {@link #getDuration() duration} set on it, the
+ * child transition will inherit that duration. Transitions are assumed to have
+ * a maximum of one transitionSet parent.</p>
+ *
+ * @param transition A non-null child transition to be added to this set.
+ * @return This transitionSet object.
+ */
+ public TransitionSet addTransition(Transition transition) {
+ if (transition != null) {
+ mTransitions.add(transition);
+ transition.mParent = this;
+ if (mDuration >= 0) {
+ transition.setDuration(mDuration);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Returns the number of child transitions in the TransitionSet.
+ *
+ * @return The number of child transitions in the TransitionSet.
+ * @see #addTransition(Transition)
+ * @see #getTransitionAt(int)
+ */
+ public int getTransitionCount() {
+ return mTransitions.size();
+ }
+
+ /**
+ * Returns the child Transition at the specified position in the TransitionSet.
+ *
+ * @param index The position of the Transition to retrieve.
+ * @see #addTransition(Transition)
+ * @see #getTransitionCount()
+ */
+ public Transition getTransitionAt(int index) {
+ if (index < 0 || index >= mTransitions.size()) {
+ return null;
+ }
+ return mTransitions.get(index);
+ }
+
+ /**
+ * Setting a non-negative duration on a TransitionSet causes all of the child
+ * transitions (current and future) to inherit this duration.
+ *
+ * @param duration The length of the animation, in milliseconds.
+ * @return This transitionSet object.
+ */
+ @Override
+ public TransitionSet setDuration(long duration) {
+ super.setDuration(duration);
+ if (mDuration >= 0 && mTransitions != null) {
+ int numTransitions = mTransitions.size();
+ for (int i = 0; i < numTransitions; ++i) {
+ mTransitions.get(i).setDuration(duration);
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public TransitionSet setStartDelay(long startDelay) {
+ return (TransitionSet) super.setStartDelay(startDelay);
+ }
+
+ @Override
+ public TransitionSet setInterpolator(TimeInterpolator interpolator) {
+ return (TransitionSet) super.setInterpolator(interpolator);
+ }
+
+ @Override
+ public TransitionSet addTarget(View target) {
+ for (int i = 0; i < mTransitions.size(); i++) {
+ mTransitions.get(i).addTarget(target);
+ }
+ return (TransitionSet) super.addTarget(target);
+ }
+
+ @Override
+ public TransitionSet addTarget(int targetId) {
+ for (int i = 0; i < mTransitions.size(); i++) {
+ mTransitions.get(i).addTarget(targetId);
+ }
+ return (TransitionSet) super.addTarget(targetId);
+ }
+
+ @Override
+ public TransitionSet addTarget(String targetName) {
+ for (int i = 0; i < mTransitions.size(); i++) {
+ mTransitions.get(i).addTarget(targetName);
+ }
+ return (TransitionSet) super.addTarget(targetName);
+ }
+
+ @Override
+ public TransitionSet addTarget(Class targetType) {
+ for (int i = 0; i < mTransitions.size(); i++) {
+ mTransitions.get(i).addTarget(targetType);
+ }
+ return (TransitionSet) super.addTarget(targetType);
+ }
+
+ @Override
+ public TransitionSet addListener(TransitionListener listener) {
+ return (TransitionSet) super.addListener(listener);
+ }
+
+ @Override
+ public TransitionSet removeTarget(int targetId) {
+ for (int i = 0; i < mTransitions.size(); i++) {
+ mTransitions.get(i).removeTarget(targetId);
+ }
+ return (TransitionSet) super.removeTarget(targetId);
+ }
+
+ @Override
+ public TransitionSet removeTarget(View target) {
+ for (int i = 0; i < mTransitions.size(); i++) {
+ mTransitions.get(i).removeTarget(target);
+ }
+ return (TransitionSet) super.removeTarget(target);
+ }
+
+ @Override
+ public TransitionSet removeTarget(Class target) {
+ for (int i = 0; i < mTransitions.size(); i++) {
+ mTransitions.get(i).removeTarget(target);
+ }
+ return (TransitionSet) super.removeTarget(target);
+ }
+
+ @Override
+ public TransitionSet removeTarget(String target) {
+ for (int i = 0; i < mTransitions.size(); i++) {
+ mTransitions.get(i).removeTarget(target);
+ }
+ return (TransitionSet) super.removeTarget(target);
+ }
+
+ @Override
+ public Transition excludeTarget(View target, boolean exclude) {
+ for (int i = 0; i < mTransitions.size(); i++) {
+ mTransitions.get(i).excludeTarget(target, exclude);
+ }
+ return super.excludeTarget(target, exclude);
+ }
+
+ @Override
+ public Transition excludeTarget(String targetName, boolean exclude) {
+ for (int i = 0; i < mTransitions.size(); i++) {
+ mTransitions.get(i).excludeTarget(targetName, exclude);
+ }
+ return super.excludeTarget(targetName, exclude);
+ }
+
+ @Override
+ public Transition excludeTarget(int targetId, boolean exclude) {
+ for (int i = 0; i < mTransitions.size(); i++) {
+ mTransitions.get(i).excludeTarget(targetId, exclude);
+ }
+ return super.excludeTarget(targetId, exclude);
+ }
+
+ @Override
+ public Transition excludeTarget(Class type, boolean exclude) {
+ for (int i = 0; i < mTransitions.size(); i++) {
+ mTransitions.get(i).excludeTarget(type, exclude);
+ }
+ return super.excludeTarget(type, exclude);
+ }
+
+ @Override
+ public TransitionSet removeListener(TransitionListener listener) {
+ return (TransitionSet) super.removeListener(listener);
+ }
+
+ @Override
+ public void setPathMotion(PathMotion pathMotion) {
+ super.setPathMotion(pathMotion);
+ for (int i = 0; i < mTransitions.size(); i++) {
+ mTransitions.get(i).setPathMotion(pathMotion);
+ }
+ }
+
+ /**
+ * Removes the specified child transition from this set.
+ *
+ * @param transition The transition to be removed.
+ * @return This transitionSet object.
+ */
+ public TransitionSet removeTransition(Transition transition) {
+ mTransitions.remove(transition);
+ transition.mParent = null;
+ return this;
+ }
+
+ /**
+ * Sets up listeners for each of the child transitions. This is used to
+ * determine when this transition set is finished (all child transitions
+ * must finish first).
+ */
+ private void setupStartEndListeners() {
+ TransitionSetListener listener = new TransitionSetListener(this);
+ for (Transition childTransition : mTransitions) {
+ childTransition.addListener(listener);
+ }
+ mCurrentListeners = mTransitions.size();
+ }
+
+ /**
+ * This listener is used to detect when all child transitions are done, at
+ * which point this transition set is also done.
+ */
+ static class TransitionSetListener extends TransitionListenerAdapter {
+ TransitionSet mTransitionSet;
+ TransitionSetListener(TransitionSet transitionSet) {
+ mTransitionSet = transitionSet;
+ }
+ @Override
+ public void onTransitionStart(Transition transition) {
+ if (!mTransitionSet.mStarted) {
+ mTransitionSet.start();
+ mTransitionSet.mStarted = true;
+ }
+ }
+
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ --mTransitionSet.mCurrentListeners;
+ if (mTransitionSet.mCurrentListeners == 0) {
+ // All child trans
+ mTransitionSet.mStarted = false;
+ mTransitionSet.end();
+ }
+ transition.removeListener(this);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ protected void createAnimators(ViewGroup sceneRoot, TransitionValuesMaps startValues,
+ TransitionValuesMaps endValues, ArrayList<TransitionValues> startValuesList,
+ ArrayList<TransitionValues> endValuesList) {
+ long startDelay = getStartDelay();
+ int numTransitions = mTransitions.size();
+ for (int i = 0; i < numTransitions; i++) {
+ Transition childTransition = mTransitions.get(i);
+ // We only set the start delay on the first transition if we are playing
+ // the transitions sequentially.
+ if (startDelay > 0 && (mPlayTogether || i == 0)) {
+ long childStartDelay = childTransition.getStartDelay();
+ if (childStartDelay > 0) {
+ childTransition.setStartDelay(startDelay + childStartDelay);
+ } else {
+ childTransition.setStartDelay(startDelay);
+ }
+ }
+ childTransition.createAnimators(sceneRoot, startValues, endValues, startValuesList,
+ endValuesList);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ protected void runAnimators() {
+ if (mTransitions.isEmpty()) {
+ start();
+ end();
+ return;
+ }
+ setupStartEndListeners();
+ int numTransitions = mTransitions.size();
+ if (!mPlayTogether) {
+ // Setup sequence with listeners
+ // TODO: Need to add listeners in such a way that we can remove them later if canceled
+ for (int i = 1; i < numTransitions; ++i) {
+ Transition previousTransition = mTransitions.get(i - 1);
+ final Transition nextTransition = mTransitions.get(i);
+ previousTransition.addListener(new TransitionListenerAdapter() {
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ nextTransition.runAnimators();
+ transition.removeListener(this);
+ }
+ });
+ }
+ Transition firstTransition = mTransitions.get(0);
+ if (firstTransition != null) {
+ firstTransition.runAnimators();
+ }
+ } else {
+ for (int i = 0; i < numTransitions; ++i) {
+ mTransitions.get(i).runAnimators();
+ }
+ }
+ }
+
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ if (isValidTarget(transitionValues.view)) {
+ for (Transition childTransition : mTransitions) {
+ if (childTransition.isValidTarget(transitionValues.view)) {
+ childTransition.captureStartValues(transitionValues);
+ transitionValues.targetedTransitions.add(childTransition);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ if (isValidTarget(transitionValues.view)) {
+ for (Transition childTransition : mTransitions) {
+ if (childTransition.isValidTarget(transitionValues.view)) {
+ childTransition.captureEndValues(transitionValues);
+ transitionValues.targetedTransitions.add(childTransition);
+ }
+ }
+ }
+ }
+
+ @Override
+ void capturePropagationValues(TransitionValues transitionValues) {
+ super.capturePropagationValues(transitionValues);
+ int numTransitions = mTransitions.size();
+ for (int i = 0; i < numTransitions; ++i) {
+ mTransitions.get(i).capturePropagationValues(transitionValues);
+ }
+ }
+
+ /** @hide */
+ @Override
+ public void pause(View sceneRoot) {
+ super.pause(sceneRoot);
+ int numTransitions = mTransitions.size();
+ for (int i = 0; i < numTransitions; ++i) {
+ mTransitions.get(i).pause(sceneRoot);
+ }
+ }
+
+ /** @hide */
+ @Override
+ public void resume(View sceneRoot) {
+ super.resume(sceneRoot);
+ int numTransitions = mTransitions.size();
+ for (int i = 0; i < numTransitions; ++i) {
+ mTransitions.get(i).resume(sceneRoot);
+ }
+ }
+
+ /** @hide */
+ @Override
+ protected void cancel() {
+ super.cancel();
+ int numTransitions = mTransitions.size();
+ for (int i = 0; i < numTransitions; ++i) {
+ mTransitions.get(i).cancel();
+ }
+ }
+
+ /** @hide */
+ @Override
+ void forceToEnd(ViewGroup sceneRoot) {
+ super.forceToEnd(sceneRoot);
+ int numTransitions = mTransitions.size();
+ for (int i = 0; i < numTransitions; ++i) {
+ mTransitions.get(i).forceToEnd(sceneRoot);
+ }
+ }
+
+ @Override
+ TransitionSet setSceneRoot(ViewGroup sceneRoot) {
+ super.setSceneRoot(sceneRoot);
+ int numTransitions = mTransitions.size();
+ for (int i = 0; i < numTransitions; ++i) {
+ mTransitions.get(i).setSceneRoot(sceneRoot);
+ }
+ return (TransitionSet) this;
+ }
+
+ @Override
+ void setCanRemoveViews(boolean canRemoveViews) {
+ super.setCanRemoveViews(canRemoveViews);
+ int numTransitions = mTransitions.size();
+ for (int i = 0; i < numTransitions; ++i) {
+ mTransitions.get(i).setCanRemoveViews(canRemoveViews);
+ }
+ }
+
+ @Override
+ public void setPropagation(TransitionPropagation propagation) {
+ super.setPropagation(propagation);
+ int numTransitions = mTransitions.size();
+ for (int i = 0; i < numTransitions; ++i) {
+ mTransitions.get(i).setPropagation(propagation);
+ }
+ }
+
+ @Override
+ public void setEpicenterCallback(EpicenterCallback epicenterCallback) {
+ super.setEpicenterCallback(epicenterCallback);
+ int numTransitions = mTransitions.size();
+ for (int i = 0; i < numTransitions; ++i) {
+ mTransitions.get(i).setEpicenterCallback(epicenterCallback);
+ }
+ }
+
+ @Override
+ String toString(String indent) {
+ String result = super.toString(indent);
+ for (int i = 0; i < mTransitions.size(); ++i) {
+ result += "\n" + mTransitions.get(i).toString(indent + " ");
+ }
+ return result;
+ }
+
+ @Override
+ public TransitionSet clone() {
+ TransitionSet clone = (TransitionSet) super.clone();
+ clone.mTransitions = new ArrayList<Transition>();
+ int numTransitions = mTransitions.size();
+ for (int i = 0; i < numTransitions; ++i) {
+ clone.addTransition((Transition) mTransitions.get(i).clone());
+ }
+ return clone;
+ }
+}