diff options
author | Justin Klaassen <justinklaassen@google.com> | 2017-09-15 17:58:39 -0400 |
---|---|---|
committer | Justin Klaassen <justinklaassen@google.com> | 2017-09-15 17:58:39 -0400 |
commit | 10d07c88d69cc64f73a069163e7ea5ba2519a099 (patch) | |
tree | 8dbd149eb350320a29c3d10e7ad3201de1c5cbee /android/transition/TransitionSet.java | |
parent | 677516fb6b6f207d373984757d3d9450474b6b00 (diff) | |
download | android-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.java | 567 |
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> + * <transitionSet xmlns:android="http://schemas.android.com/apk/res/android" + * android:transitionOrdering="sequential"> + * <fade/> + * <changeBounds/> + * </transitionSet> + * </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; + } +} |