Make Fragment Transitions match Acitivty Transitions API
Bug 17188255 Change-Id: I506a097be4010d7156caf465c95295c58612c16e
This commit is contained in:
@@ -612,12 +612,20 @@ package android {
|
||||
field public static final int format12Hour = 16843722; // 0x10103ca
|
||||
field public static final int format24Hour = 16843723; // 0x10103cb
|
||||
field public static final int fragment = 16843491; // 0x10102e3
|
||||
field public static final int fragmentAllowEnterTransitionOverlap = 16843977; // 0x10104c9
|
||||
field public static final int fragmentAllowReturnTransitionOverlap = 16843978; // 0x10104ca
|
||||
field public static final int fragmentCloseEnterAnimation = 16843495; // 0x10102e7
|
||||
field public static final int fragmentCloseExitAnimation = 16843496; // 0x10102e8
|
||||
field public static final int fragmentEnterTransition = 16843972; // 0x10104c4
|
||||
field public static final int fragmentExitTransition = 16843971; // 0x10104c3
|
||||
field public static final int fragmentFadeEnterAnimation = 16843497; // 0x10102e9
|
||||
field public static final int fragmentFadeExitAnimation = 16843498; // 0x10102ea
|
||||
field public static final int fragmentOpenEnterAnimation = 16843493; // 0x10102e5
|
||||
field public static final int fragmentOpenExitAnimation = 16843494; // 0x10102e6
|
||||
field public static final int fragmentReenterTransition = 16843976; // 0x10104c8
|
||||
field public static final int fragmentReturnTransition = 16843974; // 0x10104c6
|
||||
field public static final int fragmentSharedElementEnterTransition = 16843973; // 0x10104c5
|
||||
field public static final int fragmentSharedElementReturnTransition = 16843975; // 0x10104c7
|
||||
field public static final int freezesText = 16843116; // 0x101016c
|
||||
field public static final int fromAlpha = 16843210; // 0x10101ca
|
||||
field public static final int fromDegrees = 16843187; // 0x10101b3
|
||||
@@ -1418,7 +1426,7 @@ package android {
|
||||
field public static final int windowActionBarOverlay = 16843492; // 0x10102e4
|
||||
field public static final int windowActionModeOverlay = 16843485; // 0x10102dd
|
||||
field public static final int windowAllowEnterTransitionOverlap = 16843836; // 0x101043c
|
||||
field public static final int windowAllowExitTransitionOverlap = 16843835; // 0x101043b
|
||||
field public static final int windowAllowReturnTransitionOverlap = 16843835; // 0x101043b
|
||||
field public static final int windowAnimationStyle = 16842926; // 0x10100ae
|
||||
field public static final int windowBackground = 16842836; // 0x1010054
|
||||
field public static final int windowClipToOutline = 16843948; // 0x10104ac
|
||||
@@ -4245,14 +4253,22 @@ package android.app {
|
||||
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
|
||||
method public final boolean equals(java.lang.Object);
|
||||
method public final android.app.Activity getActivity();
|
||||
method public boolean getAllowEnterTransitionOverlap();
|
||||
method public boolean getAllowReturnTransitionOverlap();
|
||||
method public final android.os.Bundle getArguments();
|
||||
method public final android.app.FragmentManager getChildFragmentManager();
|
||||
method public android.transition.Transition getEnterTransition();
|
||||
method public android.transition.Transition getExitTransition();
|
||||
method public final android.app.FragmentManager getFragmentManager();
|
||||
method public final int getId();
|
||||
method public android.app.LoaderManager getLoaderManager();
|
||||
method public final android.app.Fragment getParentFragment();
|
||||
method public android.transition.Transition getReenterTransition();
|
||||
method public final android.content.res.Resources getResources();
|
||||
method public final boolean getRetainInstance();
|
||||
method public android.transition.Transition getReturnTransition();
|
||||
method public android.transition.Transition getSharedElementEnterTransition();
|
||||
method public android.transition.Transition getSharedElementReturnTransition();
|
||||
method public final java.lang.String getString(int);
|
||||
method public final java.lang.String getString(int, java.lang.Object...);
|
||||
method public final java.lang.String getTag();
|
||||
@@ -4301,11 +4317,21 @@ package android.app {
|
||||
method public void onViewCreated(android.view.View, android.os.Bundle);
|
||||
method public void onViewStateRestored(android.os.Bundle);
|
||||
method public void registerForContextMenu(android.view.View);
|
||||
method public void setAllowEnterTransitionOverlap(boolean);
|
||||
method public void setAllowReturnTransitionOverlap(boolean);
|
||||
method public void setArguments(android.os.Bundle);
|
||||
method public void setEnterSharedElementTransitionListener(android.app.SharedElementListener);
|
||||
method public void setEnterTransition(android.transition.Transition);
|
||||
method public void setExitSharedElementTransitionListener(android.app.SharedElementListener);
|
||||
method public void setExitTransition(android.transition.Transition);
|
||||
method public void setHasOptionsMenu(boolean);
|
||||
method public void setInitialSavedState(android.app.Fragment.SavedState);
|
||||
method public void setMenuVisibility(boolean);
|
||||
method public void setReenterTransition(android.transition.Transition);
|
||||
method public void setRetainInstance(boolean);
|
||||
method public void setReturnTransition(android.transition.Transition);
|
||||
method public void setSharedElementEnterTransition(android.transition.Transition);
|
||||
method public void setSharedElementReturnTransition(android.transition.Transition);
|
||||
method public void setTargetFragment(android.app.Fragment, int);
|
||||
method public void setUserVisibleHint(boolean);
|
||||
method public void startActivity(android.content.Intent);
|
||||
@@ -4405,7 +4431,6 @@ package android.app {
|
||||
method public abstract android.app.FragmentTransaction setBreadCrumbTitle(java.lang.CharSequence);
|
||||
method public abstract android.app.FragmentTransaction setCustomAnimations(int, int);
|
||||
method public abstract android.app.FragmentTransaction setCustomAnimations(int, int, int, int);
|
||||
method public abstract android.app.FragmentTransaction setCustomTransition(int, int);
|
||||
method public abstract android.app.FragmentTransaction setTransition(int);
|
||||
method public abstract android.app.FragmentTransaction setTransitionStyle(int);
|
||||
method public abstract android.app.FragmentTransaction show(android.app.Fragment);
|
||||
@@ -34864,7 +34889,7 @@ package android.view {
|
||||
method public abstract void closePanel(int);
|
||||
method public android.view.View findViewById(int);
|
||||
method public boolean getAllowEnterTransitionOverlap();
|
||||
method public boolean getAllowExitTransitionOverlap();
|
||||
method public boolean getAllowReturnTransitionOverlap();
|
||||
method public final android.view.WindowManager.LayoutParams getAttributes();
|
||||
method public final android.view.Window.Callback getCallback();
|
||||
method public final android.view.Window getContainer();
|
||||
@@ -34913,7 +34938,7 @@ package android.view {
|
||||
method public abstract void restoreHierarchyState(android.os.Bundle);
|
||||
method public abstract android.os.Bundle saveHierarchyState();
|
||||
method public void setAllowEnterTransitionOverlap(boolean);
|
||||
method public void setAllowExitTransitionOverlap(boolean);
|
||||
method public void setAllowReturnTransitionOverlap(boolean);
|
||||
method public void setAttributes(android.view.WindowManager.LayoutParams);
|
||||
method public abstract void setBackgroundDrawable(android.graphics.drawable.Drawable);
|
||||
method public void setBackgroundDrawableResource(int);
|
||||
|
||||
@@ -23,15 +23,17 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.transition.Transition;
|
||||
import android.transition.TransitionInflater;
|
||||
import android.transition.TransitionManager;
|
||||
import android.transition.TransitionSet;
|
||||
import android.transition.TransitionUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.util.LogWriter;
|
||||
import android.util.Pair;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@@ -42,8 +44,6 @@ final class BackStackState implements Parcelable {
|
||||
final int[] mOps;
|
||||
final int mTransition;
|
||||
final int mTransitionStyle;
|
||||
final int mCustomTransition;
|
||||
final int mSceneRoot;
|
||||
final String mName;
|
||||
final int mIndex;
|
||||
final int mBreadCrumbTitleRes;
|
||||
@@ -96,8 +96,6 @@ final class BackStackState implements Parcelable {
|
||||
mBreadCrumbTitleText = bse.mBreadCrumbTitleText;
|
||||
mBreadCrumbShortTitleRes = bse.mBreadCrumbShortTitleRes;
|
||||
mBreadCrumbShortTitleText = bse.mBreadCrumbShortTitleText;
|
||||
mCustomTransition = bse.mCustomTransition;
|
||||
mSceneRoot = bse.mSceneRoot;
|
||||
mSharedElementSourceNames = bse.mSharedElementSourceNames;
|
||||
mSharedElementTargetNames = bse.mSharedElementTargetNames;
|
||||
}
|
||||
@@ -112,8 +110,6 @@ final class BackStackState implements Parcelable {
|
||||
mBreadCrumbTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
|
||||
mBreadCrumbShortTitleRes = in.readInt();
|
||||
mBreadCrumbShortTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
|
||||
mCustomTransition = in.readInt();
|
||||
mSceneRoot = in.readInt();
|
||||
mSharedElementSourceNames = in.createStringArrayList();
|
||||
mSharedElementTargetNames = in.createStringArrayList();
|
||||
}
|
||||
@@ -164,8 +160,6 @@ final class BackStackState implements Parcelable {
|
||||
bse.mBreadCrumbTitleText = mBreadCrumbTitleText;
|
||||
bse.mBreadCrumbShortTitleRes = mBreadCrumbShortTitleRes;
|
||||
bse.mBreadCrumbShortTitleText = mBreadCrumbShortTitleText;
|
||||
bse.mCustomTransition = mCustomTransition;
|
||||
bse.mSceneRoot = mSceneRoot;
|
||||
bse.mSharedElementSourceNames = mSharedElementSourceNames;
|
||||
bse.mSharedElementTargetNames = mSharedElementTargetNames;
|
||||
bse.bumpBackStackNesting(1);
|
||||
@@ -186,8 +180,6 @@ final class BackStackState implements Parcelable {
|
||||
TextUtils.writeToParcel(mBreadCrumbTitleText, dest, 0);
|
||||
dest.writeInt(mBreadCrumbShortTitleRes);
|
||||
TextUtils.writeToParcel(mBreadCrumbShortTitleText, dest, 0);
|
||||
dest.writeInt(mCustomTransition);
|
||||
dest.writeInt(mSceneRoot);
|
||||
dest.writeStringList(mSharedElementSourceNames);
|
||||
dest.writeStringList(mSharedElementTargetNames);
|
||||
}
|
||||
@@ -254,8 +246,6 @@ final class BackStackRecord extends FragmentTransaction implements
|
||||
int mBreadCrumbShortTitleRes;
|
||||
CharSequence mBreadCrumbShortTitleText;
|
||||
|
||||
int mCustomTransition;
|
||||
int mSceneRoot;
|
||||
ArrayList<String> mSharedElementSourceNames;
|
||||
ArrayList<String> mSharedElementTargetNames;
|
||||
|
||||
@@ -572,13 +562,6 @@ final class BackStackRecord extends FragmentTransaction implements
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FragmentTransaction setCustomTransition(int sceneRootId, int transitionId) {
|
||||
mSceneRoot = sceneRootId;
|
||||
mCustomTransition = transitionId;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FragmentTransaction addSharedElement(View sharedElement, String name) {
|
||||
String transitionName = sharedElement.getTransitionName();
|
||||
@@ -760,8 +743,15 @@ final class BackStackRecord extends FragmentTransaction implements
|
||||
|
||||
bumpBackStackNesting(1);
|
||||
|
||||
TransitionState state = beginTransition(mSharedElementSourceNames,
|
||||
mSharedElementTargetNames);
|
||||
SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
|
||||
SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
|
||||
|
||||
calculateFragments(firstOutFragments, lastInFragments);
|
||||
|
||||
TransitionState state = null;
|
||||
if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) {
|
||||
state = beginTransition(firstOutFragments, lastInFragments, false);
|
||||
}
|
||||
|
||||
Op op = mHead;
|
||||
while (op != null) {
|
||||
@@ -854,142 +844,606 @@ final class BackStackRecord extends FragmentTransaction implements
|
||||
}
|
||||
|
||||
if (state != null) {
|
||||
updateTransitionEndState(state, mSharedElementTargetNames);
|
||||
updateTransitionEndState(state, firstOutFragments, lastInFragments, false);
|
||||
}
|
||||
}
|
||||
|
||||
private TransitionState beginTransition(ArrayList<String> sourceNames,
|
||||
ArrayList<String> targetNames) {
|
||||
if (mCustomTransition <= 0 || mSceneRoot <= 0) {
|
||||
return null;
|
||||
private static void setFirstOut(SparseArray<Fragment> fragments, Fragment fragment) {
|
||||
if (fragment != null) {
|
||||
int containerId = fragment.mContainerId;
|
||||
if (containerId != 0 && !fragment.isHidden() && fragment.isAdded() &&
|
||||
fragment.getView() != null && fragments.get(containerId) == null) {
|
||||
fragments.put(containerId, fragment);
|
||||
}
|
||||
}
|
||||
View rootView = mManager.mContainer.findViewById(mSceneRoot);
|
||||
if (!(rootView instanceof ViewGroup)) {
|
||||
throw new IllegalArgumentException("SceneRoot is not a ViewGroup");
|
||||
}
|
||||
TransitionState state = new TransitionState();
|
||||
// get Transition scene root and create Transitions
|
||||
state.sceneRoot = (ViewGroup) rootView;
|
||||
state.sceneRoot.captureTransitioningViews(state.transitioningViews);
|
||||
}
|
||||
|
||||
private void setLastIn(SparseArray<Fragment> fragments, Fragment fragment) {
|
||||
if (fragment != null) {
|
||||
int containerId = fragment.mContainerId;
|
||||
if (containerId != 0) {
|
||||
fragments.put(containerId, fragment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the first removed fragment and last added fragments when going forward.
|
||||
* If none of the fragments have transitions, then both lists will be empty.
|
||||
*
|
||||
* @param firstOutFragments The list of first fragments to be removed, keyed on the
|
||||
* container ID. This list will be modified by the method.
|
||||
* @param lastInFragments The list of last fragments to be added, keyed on the
|
||||
* container ID. This list will be modified by the method.
|
||||
*/
|
||||
private void calculateFragments(SparseArray<Fragment> firstOutFragments,
|
||||
SparseArray<Fragment> lastInFragments) {
|
||||
Op op = mHead;
|
||||
while (op != null) {
|
||||
switch (op.cmd) {
|
||||
case OP_ADD:
|
||||
setLastIn(lastInFragments, op.fragment);
|
||||
break;
|
||||
case OP_REPLACE: {
|
||||
Fragment f = op.fragment;
|
||||
if (mManager.mAdded != null) {
|
||||
for (int i = 0; i < mManager.mAdded.size(); i++) {
|
||||
Fragment old = mManager.mAdded.get(i);
|
||||
if (f == null || old.mContainerId == f.mContainerId) {
|
||||
if (old == f) {
|
||||
f = null;
|
||||
} else {
|
||||
setFirstOut(firstOutFragments, old);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
setLastIn(lastInFragments, f);
|
||||
break;
|
||||
}
|
||||
case OP_REMOVE:
|
||||
setFirstOut(firstOutFragments, op.fragment);
|
||||
break;
|
||||
case OP_HIDE:
|
||||
setFirstOut(firstOutFragments, op.fragment);
|
||||
break;
|
||||
case OP_SHOW:
|
||||
setLastIn(lastInFragments, op.fragment);
|
||||
break;
|
||||
case OP_DETACH:
|
||||
setFirstOut(firstOutFragments, op.fragment);
|
||||
break;
|
||||
case OP_ATTACH:
|
||||
setLastIn(lastInFragments, op.fragment);
|
||||
break;
|
||||
}
|
||||
|
||||
op = op.next;
|
||||
}
|
||||
|
||||
if (!haveTransitions(firstOutFragments, lastInFragments, false)) {
|
||||
firstOutFragments.clear();
|
||||
lastInFragments.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if custom transitions exist on any fragment in firstOutFragments or
|
||||
* lastInFragments or false otherwise.
|
||||
*/
|
||||
private static boolean haveTransitions(SparseArray<Fragment> firstOutFragments,
|
||||
SparseArray<Fragment> lastInFragments, boolean isBack) {
|
||||
for (int i = firstOutFragments.size() - 1; i >= 0; i--) {
|
||||
Fragment f = firstOutFragments.valueAt(i);
|
||||
if (isBack) {
|
||||
if (f.getReturnTransition() != null ||
|
||||
f.getSharedElementReturnTransition() != null) {
|
||||
return true;
|
||||
}
|
||||
} else if (f.getExitTransition() != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = lastInFragments.size() - 1; i >= 0; i--) {
|
||||
Fragment f = lastInFragments.valueAt(i);
|
||||
if (isBack) {
|
||||
if (f.getReenterTransition() != null) {
|
||||
return true;
|
||||
}
|
||||
} else if (f.getEnterTransition() != null ||
|
||||
f.getSharedElementEnterTransition() != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the first removed fragment and last added fragments when popping the back stack.
|
||||
* If none of the fragments have transitions, then both lists will be empty.
|
||||
*
|
||||
* @param firstOutFragments The list of first fragments to be removed, keyed on the
|
||||
* container ID. This list will be modified by the method.
|
||||
* @param lastInFragments The list of last fragments to be added, keyed on the
|
||||
* container ID. This list will be modified by the method.
|
||||
*/
|
||||
public void calculateBackFragments(SparseArray<Fragment> firstOutFragments,
|
||||
SparseArray<Fragment> lastInFragments) {
|
||||
Op op = mHead;
|
||||
while (op != null) {
|
||||
switch (op.cmd) {
|
||||
case OP_ADD:
|
||||
setFirstOut(firstOutFragments, op.fragment);
|
||||
break;
|
||||
case OP_REPLACE:
|
||||
if (op.removed != null) {
|
||||
for (int i = op.removed.size() - 1; i >= 0; i--) {
|
||||
setLastIn(lastInFragments, op.removed.get(i));
|
||||
}
|
||||
}
|
||||
setFirstOut(firstOutFragments, op.fragment);
|
||||
break;
|
||||
case OP_REMOVE:
|
||||
setLastIn(lastInFragments, op.fragment);
|
||||
break;
|
||||
case OP_HIDE:
|
||||
setLastIn(lastInFragments, op.fragment);
|
||||
break;
|
||||
case OP_SHOW:
|
||||
setFirstOut(firstOutFragments, op.fragment);
|
||||
break;
|
||||
case OP_DETACH:
|
||||
setLastIn(lastInFragments, op.fragment);
|
||||
break;
|
||||
case OP_ATTACH:
|
||||
setFirstOut(firstOutFragments, op.fragment);
|
||||
break;
|
||||
}
|
||||
|
||||
op = op.next;
|
||||
}
|
||||
|
||||
if (!haveTransitions(firstOutFragments, lastInFragments, true)) {
|
||||
firstOutFragments.clear();
|
||||
lastInFragments.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When custom fragment transitions are used, this sets up the state for each transition
|
||||
* and begins the transition. A different transition is started for each fragment container
|
||||
* and consists of up to 3 different transitions: the exit transition, a shared element
|
||||
* transition and an enter transition.
|
||||
*
|
||||
* <p>The exit transition operates against the leaf nodes of the first fragment
|
||||
* with a view that was removed. If no such fragment was removed, then no exit
|
||||
* transition is executed. The exit transition comes from the outgoing fragment.</p>
|
||||
*
|
||||
* <p>The enter transition operates against the last fragment that was added. If
|
||||
* that fragment does not have a view or no fragment was added, then no enter
|
||||
* transition is executed. The enter transition comes from the incoming fragment.</p>
|
||||
*
|
||||
* <p>The shared element transition operates against all views and comes either
|
||||
* from the outgoing fragment or the incoming fragment, depending on whether this
|
||||
* is going forward or popping the back stack. When going forward, the incoming
|
||||
* fragment's enter shared element transition is used, but when going back, the
|
||||
* outgoing fragment's return shared element transition is used. Shared element
|
||||
* transitions only operate if there is both an incoming and outgoing fragment.</p>
|
||||
*
|
||||
* @param firstOutFragments The list of first fragments to be removed, keyed on the
|
||||
* container ID.
|
||||
* @param lastInFragments The list of last fragments to be added, keyed on the
|
||||
* container ID.
|
||||
* @param isBack true if this is popping the back stack or false if this is a
|
||||
* forward operation.
|
||||
* @return The TransitionState used to complete the operation of the transition
|
||||
* in {@link #updateTransitionEndState(android.app.BackStackRecord.TransitionState,
|
||||
* android.util.SparseArray, android.util.SparseArray, boolean)}.
|
||||
*/
|
||||
private TransitionState beginTransition(SparseArray<Fragment> firstOutFragments,
|
||||
SparseArray<Fragment> lastInFragments, boolean isBack) {
|
||||
TransitionState state = new TransitionState();
|
||||
|
||||
state.exitTransition = TransitionInflater.from(mManager.mActivity)
|
||||
.inflateTransition(mCustomTransition);
|
||||
state.sharedElementTransition = TransitionInflater.from(mManager.mActivity)
|
||||
.inflateTransition(mCustomTransition);
|
||||
state.enterTransition = TransitionInflater.from(mManager.mActivity)
|
||||
.inflateTransition(mCustomTransition);
|
||||
// Adding a non-existent target view makes sure that the transitions don't target
|
||||
// any views by default. They'll only target the views we tell add. If we don't
|
||||
// add any, then no views will be targeted.
|
||||
View nonExistentView = new View(mManager.mActivity);
|
||||
state.enterTransition.addTarget(nonExistentView);
|
||||
state.exitTransition.addTarget(nonExistentView);
|
||||
state.sharedElementTransition.addTarget(nonExistentView);
|
||||
state.nonExistentView = new View(mManager.mActivity);
|
||||
|
||||
setSharedElementEpicenter(state.enterTransition, state);
|
||||
ArrayMap<String, View> tempViews1 = new ArrayMap<String, View>();
|
||||
ArrayMap<String, View> tempViews2 = new ArrayMap<String, View>();
|
||||
ArrayList<String> tempNames = new ArrayList<String>();
|
||||
ArrayList<View> tempViewList = new ArrayList<View>();
|
||||
|
||||
state.excludingTransition = new TransitionSet()
|
||||
.addTransition(state.exitTransition)
|
||||
.addTransition(state.enterTransition);
|
||||
|
||||
if (sourceNames != null) {
|
||||
// Map shared elements.
|
||||
state.sceneRoot.findNamedViews(state.namedViews);
|
||||
state.namedViews.retainAll(sourceNames);
|
||||
View epicenterView = state.namedViews.get(sourceNames.get(0));
|
||||
if (epicenterView != null) {
|
||||
// The epicenter is only the first shared element.
|
||||
setEpicenter(state.exitTransition, epicenterView);
|
||||
setEpicenter(state.sharedElementTransition, epicenterView);
|
||||
}
|
||||
state.transitioningViews.removeAll(state.namedViews.values());
|
||||
state.excludingTransition.addTransition(state.sharedElementTransition);
|
||||
addTransitioningViews(state.sharedElementTransition, state.namedViews.values());
|
||||
// Go over all leaving fragments.
|
||||
for (int i = 0; i < firstOutFragments.size(); i++) {
|
||||
int containerId = firstOutFragments.keyAt(i);
|
||||
configureTransitions(containerId, state, isBack, firstOutFragments,
|
||||
lastInFragments, tempViews1, tempViews2, tempNames, tempViewList);
|
||||
}
|
||||
|
||||
// Adds the (maybe) exiting views, not including the shared element.
|
||||
// If some stay, that's ok.
|
||||
addTransitioningViews(state.exitTransition, state.transitioningViews);
|
||||
// Now go over all entering fragments that didn't have a leaving fragment.
|
||||
for (int i = 0; i < lastInFragments.size(); i++) {
|
||||
int containerId = lastInFragments.keyAt(i);
|
||||
if (firstOutFragments.get(containerId) == null) {
|
||||
configureTransitions(containerId, state, isBack, firstOutFragments,
|
||||
lastInFragments, tempViews1, tempViews2, tempNames, tempViewList);
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare for shared element name mapping. This could be chained in the case
|
||||
// of popping several back stack states.
|
||||
state.excludingTransition.setNameOverrides(new ArrayMap<String, String>());
|
||||
setNameOverrides(state, sourceNames, targetNames);
|
||||
|
||||
// Don't include any subtree in the views that are hidden when capturing the
|
||||
// view hierarchy transitions. They should be as if not there.
|
||||
excludeHiddenFragments(state, true);
|
||||
|
||||
TransitionManager.beginDelayedTransition(state.sceneRoot, state.excludingTransition);
|
||||
if (state.overallTransitions.size() == 0) {
|
||||
state = null;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
private void updateTransitionEndState(TransitionState state, ArrayList<String> names) {
|
||||
// Find all views that are entering.
|
||||
ArrayList<View> enteringViews = new ArrayList<View>();
|
||||
state.sceneRoot.captureTransitioningViews(enteringViews);
|
||||
enteringViews.removeAll(state.transitioningViews);
|
||||
private static Transition getEnterTransition(Fragment inFragment, boolean isBack) {
|
||||
if (inFragment == null) {
|
||||
return null;
|
||||
}
|
||||
return isBack ? inFragment.getReenterTransition() : inFragment.getEnterTransition();
|
||||
}
|
||||
|
||||
if (names != null) {
|
||||
// find all shared elements.
|
||||
state.namedViews.clear();
|
||||
state.sceneRoot.findNamedViews(state.namedViews);
|
||||
state.namedViews.retainAll(names);
|
||||
if (!state.namedViews.isEmpty()) {
|
||||
enteringViews.removeAll(state.namedViews.values());
|
||||
addTransitioningViews(state.sharedElementTransition, state.namedViews.values());
|
||||
// now we know the epicenter of the entering transition.
|
||||
state.mEnteringEpicenterView = state.namedViews.get(names.get(0));
|
||||
private static Transition getExitTransition(Fragment outFragment, boolean isBack) {
|
||||
if (outFragment == null) {
|
||||
return null;
|
||||
}
|
||||
return isBack ? outFragment.getReturnTransition() : outFragment.getExitTransition();
|
||||
}
|
||||
|
||||
private static Transition getSharedElementTransition(Fragment inFragment, Fragment outFragment,
|
||||
boolean isBack) {
|
||||
if (inFragment == null || outFragment == null) {
|
||||
return null;
|
||||
}
|
||||
return isBack ? outFragment.getSharedElementReturnTransition() :
|
||||
inFragment.getSharedElementEnterTransition();
|
||||
}
|
||||
|
||||
private static Transition captureExitingViews(Transition exitTransition, Fragment outFragment,
|
||||
ArrayList<View> viewList) {
|
||||
if (exitTransition != null) {
|
||||
View root = outFragment.getView();
|
||||
viewList.clear();
|
||||
root.captureTransitioningViews(viewList);
|
||||
if (viewList.isEmpty()) {
|
||||
exitTransition = null;
|
||||
} else {
|
||||
addTransitioningViews(exitTransition, viewList);
|
||||
}
|
||||
}
|
||||
return exitTransition;
|
||||
}
|
||||
|
||||
private ArrayMap<String, View> remapSharedElements(TransitionState state, Fragment outFragment,
|
||||
ArrayMap<String, View> namedViews, ArrayMap<String, View> tempViews2, boolean isBack) {
|
||||
if (mSharedElementSourceNames != null) {
|
||||
outFragment.getView().findNamedViews(namedViews);
|
||||
if (isBack) {
|
||||
namedViews.retainAll(mSharedElementTargetNames);
|
||||
} else {
|
||||
namedViews = remapNames(mSharedElementSourceNames, mSharedElementTargetNames,
|
||||
namedViews, tempViews2);
|
||||
}
|
||||
}
|
||||
|
||||
// Add all entering views to the enter transition.
|
||||
addTransitioningViews(state.enterTransition, enteringViews);
|
||||
|
||||
// Don't allow capturing state for the newly-hidden fragments.
|
||||
excludeHiddenFragments(state, false);
|
||||
|
||||
// Allow capturing state for the newly-shown fragments
|
||||
includeVisibleFragments(state.excludingTransition);
|
||||
}
|
||||
|
||||
private void addTransitioningViews(Transition transition, Collection<View> views) {
|
||||
if (views.isEmpty()) {
|
||||
// Add a view so that we can modify the valid views at the end of the
|
||||
// fragment transaction.
|
||||
transition.addTarget(new View(mManager.mActivity));
|
||||
if (isBack) {
|
||||
outFragment.mEnterTransitionListener.remapSharedElements(
|
||||
mSharedElementTargetNames, namedViews);
|
||||
setBackNameOverrides(state, namedViews, false);
|
||||
} else {
|
||||
for (View view : views) {
|
||||
transition.addTarget(view);
|
||||
outFragment.mExitTransitionListener.remapSharedElements(
|
||||
mSharedElementTargetNames, namedViews);
|
||||
setNameOverrides(state, namedViews, false);
|
||||
}
|
||||
|
||||
return namedViews;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the enter transition by adding a non-existent view to the transition's target list
|
||||
* and setting it epicenter callback. By adding a non-existent view to the target list,
|
||||
* we can prevent any view from being targeted at the beginning of the transition.
|
||||
* We will add to the views before the end state of the transition is captured so that the
|
||||
* views will appear. At the start of the transition, we clear the list of targets so that
|
||||
* we can restore the state of the transition and use it again.
|
||||
*/
|
||||
private void prepareEnterTransition(TransitionState state, final Transition enterTransition,
|
||||
final View container, final Fragment inFragment) {
|
||||
if (enterTransition != null) {
|
||||
final ArrayList<View> enteringViews = new ArrayList<View>();
|
||||
final View nonExistentView = state.nonExistentView;
|
||||
enterTransition.addTarget(state.nonExistentView);
|
||||
enterTransition.addListener(new Transition.TransitionListenerAdapter() {
|
||||
@Override
|
||||
public void onTransitionStart(Transition transition) {
|
||||
transition.removeListener(this);
|
||||
transition.removeTarget(nonExistentView);
|
||||
int numViews = enteringViews.size();
|
||||
for (int i = 0; i < numViews; i++) {
|
||||
transition.removeTarget(enteringViews.get(i));
|
||||
}
|
||||
}
|
||||
});
|
||||
container.getViewTreeObserver().addOnPreDrawListener(
|
||||
new ViewTreeObserver.OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
container.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
View view = inFragment.getView();
|
||||
if (view != null) {
|
||||
view.captureTransitioningViews(enteringViews);
|
||||
addTransitioningViews(enterTransition, enteringViews);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
setSharedElementEpicenter(enterTransition, state);
|
||||
}
|
||||
}
|
||||
|
||||
private static Transition mergeTransitions(Transition enterTransition,
|
||||
Transition exitTransition, Transition sharedElementTransition, Fragment inFragment,
|
||||
boolean isBack) {
|
||||
boolean overlap = true;
|
||||
if (enterTransition != null && exitTransition != null) {
|
||||
overlap = isBack ? inFragment.getAllowReturnTransitionOverlap() :
|
||||
inFragment.getAllowEnterTransitionOverlap();
|
||||
}
|
||||
|
||||
Transition transition;
|
||||
if (overlap) {
|
||||
transition = TransitionUtils.mergeTransitions(enterTransition, exitTransition,
|
||||
sharedElementTransition);
|
||||
} else {
|
||||
TransitionSet staggered = new TransitionSet()
|
||||
.addTransition(exitTransition)
|
||||
.addTransition(enterTransition)
|
||||
.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
|
||||
transition = TransitionUtils.mergeTransitions(staggered, sharedElementTransition);
|
||||
}
|
||||
return transition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures custom transitions for a specific fragment container.
|
||||
*
|
||||
* @param containerId The container ID of the fragments to configure the transition for.
|
||||
* @param state The Transition State to be shared with {@link #updateTransitionEndState(
|
||||
* android.app.BackStackRecord.TransitionState, android.util.SparseArray,
|
||||
* android.util.SparseArray, boolean)} later.
|
||||
* @param firstOutFragments The list of first fragments to be removed, keyed on the
|
||||
* container ID.
|
||||
* @param lastInFragments The list of last fragments to be added, keyed on the
|
||||
* container ID.
|
||||
* @param isBack true if this is popping the back stack or false if this is a
|
||||
* forward operation.
|
||||
* @param tempViews1 A temporary mapping of names to Views, used to avoid allocation
|
||||
* inside a loop.
|
||||
* @param tempViews2 A temporary mapping of names to Views, used to avoid allocation
|
||||
* inside a loop.
|
||||
* @param tempNames A temporary list of Strings, used to avoid allocation inside a loop.
|
||||
* @param tempViewList A temporary list of Views, used to avoid allocation inside a loop.
|
||||
*/
|
||||
private void configureTransitions(int containerId, TransitionState state, boolean isBack,
|
||||
SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments,
|
||||
ArrayMap<String, View> tempViews1, ArrayMap<String, View> tempViews2,
|
||||
ArrayList<String> tempNames, ArrayList<View> tempViewList) {
|
||||
ViewGroup sceneRoot = (ViewGroup) mManager.mContainer.findViewById(containerId);
|
||||
if (sceneRoot != null) {
|
||||
Fragment inFragment = lastInFragments.get(containerId);
|
||||
Fragment outFragment = firstOutFragments.get(containerId);
|
||||
|
||||
Transition enterTransition = getEnterTransition(inFragment, isBack);
|
||||
Transition sharedElementTransition = getSharedElementTransition(inFragment, outFragment,
|
||||
isBack);
|
||||
Transition exitTransition = getExitTransition(outFragment, isBack);
|
||||
exitTransition = captureExitingViews(exitTransition, outFragment, tempViewList);
|
||||
|
||||
ArrayMap<String, View> namedViews = tempViews1;
|
||||
namedViews.clear();
|
||||
if (sharedElementTransition != null) {
|
||||
namedViews = remapSharedElements(state,
|
||||
outFragment, namedViews, tempViews2, isBack);
|
||||
}
|
||||
|
||||
// Notify the start of the transition.
|
||||
SharedElementListener listener = isBack ?
|
||||
outFragment.mEnterTransitionListener :
|
||||
inFragment.mEnterTransitionListener;
|
||||
tempNames.clear();
|
||||
tempNames.addAll(namedViews.keySet());
|
||||
tempViewList.clear();
|
||||
tempViewList.addAll(namedViews.values());
|
||||
listener.setSharedElementStart(tempNames, tempViewList, null);
|
||||
|
||||
// Set the epicenter of the exit transition
|
||||
if (mSharedElementTargetNames != null && exitTransition != null) {
|
||||
View epicenterView = namedViews.get(mSharedElementTargetNames.get(0));
|
||||
if (epicenterView != null) {
|
||||
setEpicenter(exitTransition, epicenterView);
|
||||
}
|
||||
}
|
||||
|
||||
prepareEnterTransition(state, enterTransition, sceneRoot, inFragment);
|
||||
|
||||
Transition transition = mergeTransitions(enterTransition, exitTransition,
|
||||
sharedElementTransition, inFragment, isBack);
|
||||
|
||||
if (transition != null) {
|
||||
state.overallTransitions.put(containerId, transition);
|
||||
transition.setNameOverrides(state.nameOverrides);
|
||||
// We want to exclude hidden views later, so we need a non-null list in the
|
||||
// transition now.
|
||||
transition.excludeTarget(state.nonExistentView, true);
|
||||
// Now exclude all currently hidden fragments.
|
||||
excludeHiddenFragments(state, containerId, transition);
|
||||
cleanupHiddenFragments(transition, state);
|
||||
TransitionManager.beginDelayedTransition(sceneRoot, transition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void excludeHiddenFragments(TransitionState state, boolean forceExclude) {
|
||||
if (mManager.mAdded != null) {
|
||||
for (int i = 0; i < mManager.mAdded.size(); i++) {
|
||||
Fragment fragment = mManager.mAdded.get(i);
|
||||
if (fragment.mView != null && fragment.mHidden
|
||||
&& (forceExclude || !state.hiddenViews.contains(fragment.mView))) {
|
||||
state.excludingTransition.excludeTarget(fragment.mView, true);
|
||||
state.hiddenViews.add(fragment.mView);
|
||||
/**
|
||||
* Remaps a name-to-View map, substituting different names for keys.
|
||||
*
|
||||
* @param inMap A list of keys found in the map, in the order in toGoInMap
|
||||
* @param toGoInMap A list of keys to use for the new map, in the order of inMap
|
||||
* @param namedViews The current mapping
|
||||
* @param tempMap A temporary mapping that will be filled with the new values.
|
||||
* @return tempMap after it has been mapped with the new names as keys.
|
||||
*/
|
||||
private static ArrayMap<String, View> remapNames(ArrayList<String> inMap,
|
||||
ArrayList<String> toGoInMap, ArrayMap<String, View> namedViews,
|
||||
ArrayMap<String, View> tempMap) {
|
||||
tempMap.clear();
|
||||
if (!namedViews.isEmpty()) {
|
||||
int numKeys = inMap.size();
|
||||
for (int i = 0; i < numKeys; i++) {
|
||||
View view = namedViews.get(inMap.get(i));
|
||||
if (view != null) {
|
||||
tempMap.put(toGoInMap.get(i), view);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (forceExclude && state.hiddenViews.isEmpty()) {
|
||||
state.excludingTransition.excludeTarget(new View(mManager.mActivity), true);
|
||||
return tempMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* After making all fragment changes, this updates the custom transitions to take into
|
||||
* account the entering views and any remapping.
|
||||
*
|
||||
* @param state The transition State as returned from {@link #beginTransition(
|
||||
* android.util.SparseArray, android.util.SparseArray, boolean)}.
|
||||
* @param outFragments The list of first fragments to be removed, keyed on the
|
||||
* container ID.
|
||||
* @param inFragments The list of last fragments to be added, keyed on the
|
||||
* container ID.
|
||||
* @param isBack true if this is popping the back stack or false if this is a
|
||||
* forward operation.
|
||||
*/
|
||||
private void updateTransitionEndState(TransitionState state, SparseArray<Fragment> outFragments,
|
||||
SparseArray<Fragment> inFragments, boolean isBack) {
|
||||
ArrayMap<String, View> tempViews1 = new ArrayMap<String, View>();
|
||||
ArrayMap<String, View> tempViews2 = new ArrayMap<String, View>();
|
||||
ArrayList<String> tempNames = new ArrayList<String>();
|
||||
ArrayList<View> tempViews = new ArrayList<View>();
|
||||
|
||||
int numInFragments = inFragments.size();
|
||||
for (int i = 0; i < numInFragments; i++) {
|
||||
Fragment inFragment = inFragments.valueAt(i);
|
||||
tempViews1.clear();
|
||||
ArrayMap<String, View> namedViews = mapEnteringSharedElements(inFragment, tempViews1,
|
||||
tempViews2, isBack);
|
||||
// remap shared elements and set the name mapping used in the shared element transition.
|
||||
if (isBack) {
|
||||
inFragment.mExitTransitionListener.remapSharedElements(
|
||||
mSharedElementTargetNames, namedViews);
|
||||
setBackNameOverrides(state, namedViews, true);
|
||||
} else {
|
||||
inFragment.mEnterTransitionListener.remapSharedElements(
|
||||
mSharedElementTargetNames, namedViews);
|
||||
setNameOverrides(state, namedViews, true);
|
||||
}
|
||||
|
||||
if (mSharedElementTargetNames != null && !namedViews.isEmpty()) {
|
||||
// now we know the epicenter of the entering transition.
|
||||
View epicenter = namedViews.get(mSharedElementTargetNames.get(0));
|
||||
if (epicenter != null) {
|
||||
state.enteringEpicenterView = epicenter;
|
||||
}
|
||||
}
|
||||
|
||||
int containerId = inFragments.keyAt(i);
|
||||
SharedElementListener sharedElementListener = isBack ?
|
||||
outFragments.get(containerId).mEnterTransitionListener :
|
||||
inFragment.mEnterTransitionListener;
|
||||
tempNames.clear();
|
||||
tempNames.addAll(namedViews.keySet());
|
||||
tempViews.clear();
|
||||
tempViews.addAll(namedViews.values());
|
||||
sharedElementListener.setSharedElementEnd(tempNames, tempViews, null);
|
||||
}
|
||||
|
||||
// Don't include any newly-hidden fragments in the transition.
|
||||
excludeHiddenFragments(state);
|
||||
}
|
||||
|
||||
private ArrayMap<String, View> mapEnteringSharedElements(Fragment inFragment,
|
||||
ArrayMap<String, View> namedViews, ArrayMap<String, View> tempViews2, boolean isBack) {
|
||||
View root = inFragment.getView();
|
||||
if (root != null) {
|
||||
if (mSharedElementSourceNames != null) {
|
||||
root.findNamedViews(namedViews);
|
||||
if (isBack) {
|
||||
namedViews = remapNames(mSharedElementSourceNames,
|
||||
mSharedElementTargetNames, namedViews, tempViews2);
|
||||
} else {
|
||||
namedViews.retainAll(mSharedElementTargetNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
return namedViews;
|
||||
}
|
||||
|
||||
private static void cleanupHiddenFragments(Transition transition, TransitionState state) {
|
||||
final ArrayList<View> hiddenViews = state.hiddenFragmentViews;
|
||||
transition.addListener(new Transition.TransitionListenerAdapter() {
|
||||
@Override
|
||||
public void onTransitionStart(Transition transition) {
|
||||
transition.removeListener(this);
|
||||
int numViews = hiddenViews.size();
|
||||
for (int i = 0; i < numViews; i++) {
|
||||
transition.excludeTarget(hiddenViews.get(i), false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void excludeHiddenFragments(TransitionState state, int containerId,
|
||||
Transition transition) {
|
||||
if (mManager.mAdded != null) {
|
||||
for (int i = 0; i < mManager.mAdded.size(); i++) {
|
||||
Fragment fragment = mManager.mAdded.get(i);
|
||||
if (fragment.mView != null && fragment.mContainer != null &&
|
||||
fragment.mContainerId == containerId) {
|
||||
if (fragment.mHidden) {
|
||||
if (!state.hiddenFragmentViews.contains(fragment.mView)) {
|
||||
transition.excludeTarget(fragment.mView, true);
|
||||
state.hiddenFragmentViews.add(fragment.mView);
|
||||
}
|
||||
} else {
|
||||
transition.excludeTarget(fragment.mView, false);
|
||||
state.hiddenFragmentViews.remove(fragment.mView);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void includeVisibleFragments(Transition transition) {
|
||||
if (mManager.mAdded != null) {
|
||||
for (int i = 0; i < mManager.mAdded.size(); i++) {
|
||||
Fragment fragment = mManager.mAdded.get(i);
|
||||
if (fragment.mView != null && !fragment.mHidden) {
|
||||
transition.excludeTarget(fragment.mView, false);
|
||||
private void excludeHiddenFragments(TransitionState state) {
|
||||
int numTransitions = state.overallTransitions.size();
|
||||
for (int i = 0; i < numTransitions; i++) {
|
||||
Transition transition = state.overallTransitions.valueAt(i);
|
||||
int containerId = state.overallTransitions.keyAt(i);
|
||||
excludeHiddenFragments(state, containerId, transition);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addTransitioningViews(Transition transition, final Collection<View> views) {
|
||||
for (View view : views) {
|
||||
transition.addTarget(view);
|
||||
}
|
||||
|
||||
transition.addListener(new Transition.TransitionListenerAdapter() {
|
||||
@Override
|
||||
public void onTransitionStart(Transition transition) {
|
||||
transition.removeListener(this);
|
||||
for (View view : views) {
|
||||
transition.removeTarget(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void setEpicenter(Transition transition, View view) {
|
||||
@@ -1010,16 +1464,17 @@ final class BackStackRecord extends FragmentTransaction implements
|
||||
|
||||
@Override
|
||||
public Rect onGetEpicenter(Transition transition) {
|
||||
if (mEpicenter == null && state.mEnteringEpicenterView != null) {
|
||||
if (mEpicenter == null && state.enteringEpicenterView != null) {
|
||||
mEpicenter = new Rect();
|
||||
state.mEnteringEpicenterView.getBoundsOnScreen(mEpicenter);
|
||||
state.enteringEpicenterView.getBoundsOnScreen(mEpicenter);
|
||||
}
|
||||
return mEpicenter;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public TransitionState popFromBackStack(boolean doStateMove, TransitionState state) {
|
||||
public TransitionState popFromBackStack(boolean doStateMove, TransitionState state,
|
||||
SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments) {
|
||||
if (FragmentManagerImpl.DEBUG) {
|
||||
Log.v(TAG, "popFromBackStack: " + this);
|
||||
LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
|
||||
@@ -1029,8 +1484,10 @@ final class BackStackRecord extends FragmentTransaction implements
|
||||
}
|
||||
|
||||
if (state == null) {
|
||||
state = beginTransition(mSharedElementTargetNames, mSharedElementSourceNames);
|
||||
} else {
|
||||
if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) {
|
||||
state = beginTransition(firstOutFragments, lastInFragments, true);
|
||||
}
|
||||
} else if (!doStateMove) {
|
||||
setNameOverrides(state, mSharedElementTargetNames, mSharedElementSourceNames);
|
||||
}
|
||||
|
||||
@@ -1110,7 +1567,7 @@ final class BackStackRecord extends FragmentTransaction implements
|
||||
mManager.moveToState(mManager.mCurState,
|
||||
FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle, true);
|
||||
if (state != null) {
|
||||
updateTransitionEndState(state, mSharedElementSourceNames);
|
||||
updateTransitionEndState(state, firstOutFragments, lastInFragments, true);
|
||||
state = null;
|
||||
}
|
||||
}
|
||||
@@ -1122,15 +1579,17 @@ final class BackStackRecord extends FragmentTransaction implements
|
||||
return state;
|
||||
}
|
||||
|
||||
private static void setNameOverride(Transition transition, String source, String target) {
|
||||
ArrayMap<String, String> overrides = transition.getNameOverrides();
|
||||
for (int index = 0; index < overrides.size(); index++) {
|
||||
if (source.equals(overrides.valueAt(index))) {
|
||||
overrides.setValueAt(index, target);
|
||||
return;
|
||||
private static void setNameOverride(ArrayMap<String, String> overrides,
|
||||
String source, String target) {
|
||||
if (source != null && target != null && !source.equals(target)) {
|
||||
for (int index = 0; index < overrides.size(); index++) {
|
||||
if (source.equals(overrides.valueAt(index))) {
|
||||
overrides.setValueAt(index, target);
|
||||
return;
|
||||
}
|
||||
}
|
||||
overrides.put(source, target);
|
||||
}
|
||||
overrides.put(source, target);
|
||||
}
|
||||
|
||||
private static void setNameOverrides(TransitionState state, ArrayList<String> sourceNames,
|
||||
@@ -1139,7 +1598,36 @@ final class BackStackRecord extends FragmentTransaction implements
|
||||
for (int i = 0; i < sourceNames.size(); i++) {
|
||||
String source = sourceNames.get(i);
|
||||
String target = targetNames.get(i);
|
||||
setNameOverride(state.excludingTransition, source, target);
|
||||
setNameOverride(state.nameOverrides, source, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setBackNameOverrides(TransitionState state, ArrayMap<String, View> namedViews,
|
||||
boolean isEnd) {
|
||||
int count = mSharedElementTargetNames.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
String source = mSharedElementSourceNames.get(i);
|
||||
String originalTarget = mSharedElementTargetNames.get(i);
|
||||
String target = namedViews.get(originalTarget).getTransitionName();
|
||||
if (isEnd) {
|
||||
setNameOverride(state.nameOverrides, source, target);
|
||||
} else {
|
||||
setNameOverride(state.nameOverrides, target, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setNameOverrides(TransitionState state, ArrayMap<String, View> namedViews,
|
||||
boolean isEnd) {
|
||||
int count = namedViews.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
String source = namedViews.keyAt(i);
|
||||
String target = namedViews.valueAt(i).getTransitionName();
|
||||
if (isEnd) {
|
||||
setNameOverride(state.nameOverrides, source, target);
|
||||
} else {
|
||||
setNameOverride(state.nameOverrides, target, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1161,14 +1649,11 @@ final class BackStackRecord extends FragmentTransaction implements
|
||||
}
|
||||
|
||||
public class TransitionState {
|
||||
public ArrayList<View> hiddenViews = new ArrayList<View>();
|
||||
public ArrayList<View> transitioningViews = new ArrayList<View>();
|
||||
public ArrayMap<String, View> namedViews = new ArrayMap<String, View>();
|
||||
public Transition exitTransition;
|
||||
public Transition sharedElementTransition;
|
||||
public Transition enterTransition;
|
||||
public TransitionSet excludingTransition;
|
||||
public ViewGroup sceneRoot;
|
||||
public View mEnteringEpicenterView;
|
||||
public SparseArray<Transition> overallTransitions = new SparseArray<Transition>();
|
||||
public ArrayMap<String, String> nameOverrides = new ArrayMap<String, String>();
|
||||
public ArrayList<View> hiddenFragmentViews = new ArrayList<View>();
|
||||
|
||||
public View enteringEpicenterView;
|
||||
public View nonExistentView;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1497,7 +1497,10 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
|
||||
return false;
|
||||
}
|
||||
final BackStackRecord bss = mBackStack.remove(last);
|
||||
bss.popFromBackStack(true, null);
|
||||
SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
|
||||
SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
|
||||
bss.calculateBackFragments(firstOutFragments, lastInFragments);
|
||||
bss.popFromBackStack(true, null, firstOutFragments, lastInFragments);
|
||||
reportBackStackChanged();
|
||||
} else {
|
||||
int index = -1;
|
||||
@@ -1541,10 +1544,16 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
|
||||
states.add(mBackStack.remove(i));
|
||||
}
|
||||
final int LAST = states.size()-1;
|
||||
SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
|
||||
SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
|
||||
for (int i=0; i<=LAST; i++) {
|
||||
states.get(i).calculateBackFragments(firstOutFragments, lastInFragments);
|
||||
}
|
||||
BackStackRecord.TransitionState state = null;
|
||||
for (int i=0; i<=LAST; i++) {
|
||||
if (DEBUG) Log.v(TAG, "Popping back stack state: " + states.get(i));
|
||||
state = states.get(i).popFromBackStack(i == LAST, state);
|
||||
state = states.get(i).popFromBackStack(i == LAST, state,
|
||||
firstOutFragments, lastInFragments);
|
||||
}
|
||||
reportBackStackChanged();
|
||||
}
|
||||
|
||||
@@ -172,19 +172,16 @@ public abstract class FragmentTransaction {
|
||||
public abstract FragmentTransaction setTransition(int transit);
|
||||
|
||||
/**
|
||||
* Set a {@link android.transition.Transition} resource id to use with this transaction.
|
||||
* <var>transitionId</var> will be played for fragments when going forward and when popping
|
||||
* the back stack.
|
||||
* @param sceneRootId The ID of the element acting as the scene root for the transition.
|
||||
* This should be a ViewGroup containing all Fragments in the transaction.
|
||||
* @param transitionId The resource ID for the Transition used during the Fragment transaction.
|
||||
* TODO: remove from API
|
||||
* @hide
|
||||
*/
|
||||
public abstract FragmentTransaction setCustomTransition(int sceneRootId, int transitionId);
|
||||
public FragmentTransaction setCustomTransition(int sceneRootId, int transitionId) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used with {@link #setCustomTransition(int, int)} to map a View from a removed or hidden
|
||||
* Fragment to a View from a shown or added Fragment.
|
||||
* <var>sharedElement</var> must have a unique transitionName in the View hierarchy.
|
||||
* Used with to map a View from a removed or hidden Fragment to a View from a shown
|
||||
* or added Fragment.
|
||||
* @param sharedElement A View in a disappearing Fragment to match with a View in an
|
||||
* appearing Fragment.
|
||||
* @param name The transitionName for a View in an appearing Fragment to match to the shared
|
||||
|
||||
@@ -40,6 +40,33 @@ public class TransitionUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static Transition mergeTransitions(Transition... transitions) {
|
||||
int count = 0;
|
||||
int nonNullIndex = -1;
|
||||
for (int i = 0; i < transitions.length; i++) {
|
||||
if (transitions[i] != null) {
|
||||
count++;
|
||||
nonNullIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
return transitions[nonNullIndex];
|
||||
}
|
||||
|
||||
TransitionSet transitionSet = new TransitionSet();
|
||||
for (int i = 0; i < transitions.length; i++) {
|
||||
if (transitions[i] != null) {
|
||||
transitionSet.addTransition(transitions[i]);
|
||||
}
|
||||
}
|
||||
return transitionSet;
|
||||
}
|
||||
|
||||
public static class MatrixEvaluator implements TypeEvaluator<Matrix> {
|
||||
|
||||
float[] mTempStartValues = new float[9];
|
||||
|
||||
@@ -1430,7 +1430,9 @@ public abstract class Window {
|
||||
* {@link android.transition.Visibility} as entering is governed by changing visibility from
|
||||
* {@link View#INVISIBLE} to {@link View#VISIBLE}. If <code>transition</code> is null,
|
||||
* entering Views will remain unaffected.
|
||||
*
|
||||
* @param transition The Transition to use to move Views into the initial Scene.
|
||||
* @attr ref android.R.styleable#Window_windowEnterTransition
|
||||
*/
|
||||
public void setEnterTransition(Transition transition) {}
|
||||
|
||||
@@ -1444,8 +1446,10 @@ public abstract class Window {
|
||||
* {@link View#VISIBLE} to {@link View#INVISIBLE}. If <code>transition</code> is null,
|
||||
* entering Views will remain unaffected. If nothing is set, the default will be to
|
||||
* use the same value as set in {@link #setEnterTransition(android.transition.Transition)}.
|
||||
*
|
||||
* @param transition The Transition to use to move Views out of the Scene when the Window
|
||||
* is preparing to close.
|
||||
* @attr ref android.R.styleable#Window_windowReturnTransition
|
||||
*/
|
||||
public void setReturnTransition(Transition transition) {}
|
||||
|
||||
@@ -1456,8 +1460,10 @@ public abstract class Window {
|
||||
* {@link android.transition.Visibility} as exiting is governed by changing visibility
|
||||
* from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will
|
||||
* remain unaffected. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
*
|
||||
* @param transition The Transition to use to move Views out of the scene when calling a
|
||||
* new Activity.
|
||||
* @attr ref android.R.styleable#Window_windowExitTransition
|
||||
*/
|
||||
public void setExitTransition(Transition transition) {}
|
||||
|
||||
@@ -1470,8 +1476,10 @@ public abstract class Window {
|
||||
* the views will remain unaffected. If nothing is set, the default will be to use the same
|
||||
* transition as {@link #setExitTransition(android.transition.Transition)}.
|
||||
* Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
*
|
||||
* @param transition The Transition to use to move Views into the scene when reentering from a
|
||||
* previously-started Activity.
|
||||
* @attr ref android.R.styleable#Window_windowReenterTransition
|
||||
*/
|
||||
public void setReenterTransition(Transition transition) {}
|
||||
|
||||
@@ -1484,6 +1492,7 @@ public abstract class Window {
|
||||
* entering Views will remain unaffected. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
*
|
||||
* @return the Transition to use to move Views into the initial Scene.
|
||||
* @attr ref android.R.styleable#Window_windowEnterTransition
|
||||
*/
|
||||
public Transition getEnterTransition() { return null; }
|
||||
|
||||
@@ -1495,8 +1504,10 @@ public abstract class Window {
|
||||
* {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
|
||||
* {@link android.transition.Visibility} as entering is governed by changing visibility from
|
||||
* {@link View#VISIBLE} to {@link View#INVISIBLE}.
|
||||
*
|
||||
* @return The Transition to use to move Views out of the Scene when the Window
|
||||
* is preparing to close.
|
||||
* @attr ref android.R.styleable#Window_windowReturnTransition
|
||||
*/
|
||||
public Transition getReturnTransition() { return null; }
|
||||
|
||||
@@ -1507,8 +1518,10 @@ public abstract class Window {
|
||||
* {@link android.transition.Visibility} as exiting is governed by changing visibility
|
||||
* from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will
|
||||
* remain unaffected. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
*
|
||||
* @return the Transition to use to move Views out of the scene when calling a
|
||||
* new Activity.
|
||||
* @attr ref android.R.styleable#Window_windowExitTransition
|
||||
*/
|
||||
public Transition getExitTransition() { return null; }
|
||||
|
||||
@@ -1519,8 +1532,10 @@ public abstract class Window {
|
||||
* will extend {@link android.transition.Visibility} as exiting is governed by changing
|
||||
* visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}.
|
||||
* Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
*
|
||||
* @return The Transition to use to move Views into the scene when reentering from a
|
||||
* previously-started Activity.
|
||||
* @attr ref android.R.styleable#Window_windowReenterTransition
|
||||
*/
|
||||
public Transition getReenterTransition() { return null; }
|
||||
|
||||
@@ -1530,8 +1545,10 @@ public abstract class Window {
|
||||
* {@link android.transition.ChangeBounds}. A null
|
||||
* value will cause transferred shared elements to blink to the final position.
|
||||
* Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
*
|
||||
* @param transition The Transition to use for shared elements transferred into the content
|
||||
* Scene.
|
||||
* @attr ref android.R.styleable#Window_windowSharedElementEnterTransition
|
||||
*/
|
||||
public void setSharedElementEnterTransition(Transition transition) {}
|
||||
|
||||
@@ -1543,22 +1560,28 @@ public abstract class Window {
|
||||
* If no value is set, the default will be to use the same value as
|
||||
* {@link #setSharedElementEnterTransition(android.transition.Transition)}.
|
||||
* Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
*
|
||||
* @param transition The Transition to use for shared elements transferred out of the content
|
||||
* Scene.
|
||||
* @attr ref android.R.styleable#Window_windowSharedElementReturnTransition
|
||||
*/
|
||||
public void setSharedElementReturnTransition(Transition transition) {}
|
||||
|
||||
/**
|
||||
* Returns the Transition that will be used for shared elements transferred into the content
|
||||
* Scene. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
*
|
||||
* @return Transition to use for sharend elements transferred into the content Scene.
|
||||
* @attr ref android.R.styleable#Window_windowSharedElementEnterTransition
|
||||
*/
|
||||
public Transition getSharedElementEnterTransition() { return null; }
|
||||
|
||||
/**
|
||||
* Returns the Transition that will be used for shared elements transferred back to a
|
||||
* calling Activity. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
*
|
||||
* @return Transition to use for sharend elements transferred into the content Scene.
|
||||
* @attr ref android.R.styleable#Window_windowSharedElementReturnTransition
|
||||
*/
|
||||
public Transition getSharedElementReturnTransition() { return null; }
|
||||
|
||||
@@ -1568,8 +1591,10 @@ public abstract class Window {
|
||||
* must animate during the exit transition, this Transition should be used. Upon completion,
|
||||
* the shared elements may be transferred to the started Activity.
|
||||
* Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
*
|
||||
* @param transition The Transition to use for shared elements in the launching Window
|
||||
* prior to transferring to the launched Activity's Window.
|
||||
* @attr ref android.R.styleable#Window_windowSharedElementExitTransition
|
||||
*/
|
||||
public void setSharedElementExitTransition(Transition transition) {}
|
||||
|
||||
@@ -1579,8 +1604,10 @@ public abstract class Window {
|
||||
* is set, this will default to
|
||||
* {@link #setSharedElementExitTransition(android.transition.Transition)}.
|
||||
* Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
*
|
||||
* @param transition The Transition to use for shared elements in the launching Window
|
||||
* after the shared element has returned to the Window.
|
||||
* @attr ref android.R.styleable#Window_windowSharedElementReenterTransition
|
||||
*/
|
||||
public void setSharedElementReenterTransition(Transition transition) {}
|
||||
|
||||
@@ -1591,6 +1618,7 @@ public abstract class Window {
|
||||
*
|
||||
* @return the Transition to use for shared elements in the launching Window prior
|
||||
* to transferring to the launched Activity's Window.
|
||||
* @attr ref android.R.styleable#Window_windowSharedElementExitTransition
|
||||
*/
|
||||
public Transition getSharedElementExitTransition() { return null; }
|
||||
|
||||
@@ -1601,6 +1629,7 @@ public abstract class Window {
|
||||
*
|
||||
* @return the Transition that will be used for shared elements reentering from a started
|
||||
* Activity after it has returned the shared element to it start location.
|
||||
* @attr ref android.R.styleable#Window_windowSharedElementReenterTransition
|
||||
*/
|
||||
public Transition getSharedElementReenterTransition() { return null; }
|
||||
|
||||
@@ -1610,8 +1639,10 @@ public abstract class Window {
|
||||
* transition of the calling Activity. When true, the transition will start as soon as possible.
|
||||
* When false, the transition will wait until the remote exiting transition completes before
|
||||
* starting.
|
||||
*
|
||||
* @param allow true to start the enter transition when possible or false to
|
||||
* wait until the exiting transition completes.
|
||||
* @attr ref android.R.styleable#Window_windowAllowEnterTransitionOverlap
|
||||
*/
|
||||
public void setAllowEnterTransitionOverlap(boolean allow) {}
|
||||
|
||||
@@ -1621,8 +1652,10 @@ public abstract class Window {
|
||||
* transition of the calling Activity. When true, the transition will start as soon as possible.
|
||||
* When false, the transition will wait until the remote exiting transition completes before
|
||||
* starting.
|
||||
*
|
||||
* @return true when the enter transition should start as soon as possible or false to
|
||||
* when it should wait until the exiting transition completes.
|
||||
* @attr ref android.R.styleable#Window_windowAllowEnterTransitionOverlap
|
||||
*/
|
||||
public boolean getAllowEnterTransitionOverlap() { return true; }
|
||||
|
||||
@@ -1632,10 +1665,20 @@ public abstract class Window {
|
||||
* transition of the called Activity when reentering after if finishes. When true,
|
||||
* the transition will start as soon as possible. When false, the transition will wait
|
||||
* until the called Activity's exiting transition completes before starting.
|
||||
*
|
||||
* @param allow true to start the transition when possible or false to wait until the
|
||||
* called Activity's exiting transition completes.
|
||||
* @attr ref android.R.styleable#Window_windowAllowReturnTransitionOverlap
|
||||
*/
|
||||
public void setAllowExitTransitionOverlap(boolean allow) {}
|
||||
public void setAllowReturnTransitionOverlap(boolean allow) {}
|
||||
|
||||
/**
|
||||
* TODO: remove this.
|
||||
* @hide
|
||||
*/
|
||||
public void setAllowExitTransitionOverlap(boolean allow) {
|
||||
setAllowReturnTransitionOverlap(allow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how the transition set in
|
||||
@@ -1643,10 +1686,18 @@ public abstract class Window {
|
||||
* transition of the called Activity when reentering after if finishes. When true,
|
||||
* the transition will start as soon as possible. When false, the transition will wait
|
||||
* until the called Activity's exiting transition completes before starting.
|
||||
*
|
||||
* @return true when the transition should start when possible or false when it should wait
|
||||
* until the called Activity's exiting transition completes.
|
||||
* @attr ref android.R.styleable#Window_windowAllowReturnTransitionOverlap
|
||||
*/
|
||||
public boolean getAllowExitTransitionOverlap() { return true; }
|
||||
public boolean getAllowReturnTransitionOverlap() { return true; }
|
||||
|
||||
/**
|
||||
* TODO: remove this.
|
||||
* @hide
|
||||
*/
|
||||
public boolean getAllowExitTransitionOverlap() { return getAllowReturnTransitionOverlap(); }
|
||||
|
||||
/**
|
||||
* Returns the duration, in milliseconds, of the window background fade
|
||||
@@ -1654,8 +1705,10 @@ public abstract class Window {
|
||||
* <p>When executing the enter transition, the background starts transparent
|
||||
* and fades in. This requires {@link #FEATURE_CONTENT_TRANSITIONS}. The default is
|
||||
* 300 milliseconds.</p>
|
||||
*
|
||||
* @return The duration of the window background fade to opaque during enter transition.
|
||||
* @see #getEnterTransition()
|
||||
* @attr ref android.R.styleable#Window_windowTransitionBackgroundFadeDuration
|
||||
*/
|
||||
public long getTransitionBackgroundFadeDuration() { return 0; }
|
||||
|
||||
@@ -1665,9 +1718,11 @@ public abstract class Window {
|
||||
* <p>When executing the enter transition, the background starts transparent
|
||||
* and fades in. This requires {@link #FEATURE_CONTENT_TRANSITIONS}. The default is
|
||||
* 300 milliseconds.</p>
|
||||
*
|
||||
* @param fadeDurationMillis The duration of the window background fade to or from opaque
|
||||
* during enter transition.
|
||||
* @see #setEnterTransition(android.transition.Transition)
|
||||
* @attr ref android.R.styleable#Window_windowTransitionBackgroundFadeDuration
|
||||
*/
|
||||
public void setTransitionBackgroundFadeDuration(long fadeDurationMillis) { }
|
||||
|
||||
@@ -1679,6 +1734,7 @@ public abstract class Window {
|
||||
* @return <code>true</code> when shared elements should use an Overlay during
|
||||
* shared element transitions or <code>false</code> when they should animate as
|
||||
* part of the normal View hierarchy.
|
||||
* @attr ref android.R.styleable#Window_windowSharedElementsUseOverlay
|
||||
*/
|
||||
public boolean getSharedElementsUseOverlay() { return true; }
|
||||
|
||||
@@ -1689,6 +1745,7 @@ public abstract class Window {
|
||||
* @param sharedElementsUseOverlay <code>true</code> indicates that shared elements should
|
||||
* be transitioned with an Overlay or <code>false</code>
|
||||
* to transition within the normal View hierarchy.
|
||||
* @attr ref android.R.styleable#Window_windowSharedElementsUseOverlay
|
||||
*/
|
||||
public void setSharedElementsUseOverlay(boolean sharedElementsUseOverlay) { }
|
||||
|
||||
|
||||
@@ -514,8 +514,8 @@
|
||||
<!-- Flag indicating whether this Window's transition should overlap with
|
||||
the exiting transition of the called Activity when the called Activity
|
||||
finishes. Corresponds to
|
||||
{@link android.view.Window#setAllowExitTransitionOverlap(boolean)}. -->
|
||||
<attr name="windowAllowExitTransitionOverlap" format="boolean"/>
|
||||
{@link android.view.Window#setAllowReturnTransitionOverlap(boolean)}. -->
|
||||
<attr name="windowAllowReturnTransitionOverlap" format="boolean"/>
|
||||
|
||||
<!-- Indicates whether or not shared elements should use an overlay
|
||||
during transitions. The default value is true. -->
|
||||
@@ -1853,8 +1853,8 @@
|
||||
<!-- Flag indicating whether this Window's transition should overlap with
|
||||
the exiting transition of the called Activity when the called Activity
|
||||
finishes. Corresponds to
|
||||
{@link android.view.Window#setAllowExitTransitionOverlap(boolean)}. -->
|
||||
<attr name="windowAllowExitTransitionOverlap"/>
|
||||
{@link android.view.Window#setAllowReturnTransitionOverlap(boolean)}. -->
|
||||
<attr name="windowAllowReturnTransitionOverlap"/>
|
||||
|
||||
<!-- Indicates whether or not shared elements should use an overlay
|
||||
during transitions. The default value is true. -->
|
||||
@@ -6627,6 +6627,53 @@
|
||||
IDs (through the android:id attribute) instead of tags because
|
||||
they are faster and allow for compile-time type checking. -->
|
||||
<attr name="tag" />
|
||||
|
||||
<!-- The Transition that will be used to move Views out of the scene when the
|
||||
fragment is removed, hidden, or detached when not popping the back stack.
|
||||
Corresponds to {@link android.app.Fragment#setExitTransition(
|
||||
android.transition.Transition)} -->
|
||||
<attr name="fragmentExitTransition" format="reference"/>
|
||||
|
||||
<!-- The Transition that will be used to move Views into the initial scene.
|
||||
Corresponds to {@link android.app.Fragment#setEnterTransition(
|
||||
android.transition.Transition)} -->
|
||||
<attr name="fragmentEnterTransition" format="reference"/>
|
||||
|
||||
<!-- The Transition that will be used for shared elements transferred into the content
|
||||
Scene.
|
||||
Corresponds to {@link android.app.Fragment#setSharedElementEnterTransition(
|
||||
android.transition.Transition)} -->
|
||||
<attr name="fragmentSharedElementEnterTransition" format="reference"/>
|
||||
|
||||
<!-- The Transition that will be used to move Views out of the scene when the Fragment is
|
||||
preparing to be removed, hidden, or detached because of popping the back stack.
|
||||
Corresponds to {@link android.app.Fragment#setReturnTransition(
|
||||
android.transition.Transition)} -->
|
||||
<attr name="fragmentReturnTransition" format="reference"/>
|
||||
|
||||
<!-- The Transition that will be used for shared elements transferred back during a
|
||||
pop of the back stack. This Transition acts in the leaving Fragment.
|
||||
Corresponds to {@link android.app.Fragment#setSharedElementReturnTransition(
|
||||
android.transition.Transition)} -->
|
||||
<attr name="fragmentSharedElementReturnTransition" format="reference"/>
|
||||
|
||||
<!-- The Transition that will be used to move Views in to the scene when returning due
|
||||
to popping a back stack.
|
||||
Corresponds to {@link android.app.Fragment#setReenterTransition(
|
||||
android.transition.Transition)} -->
|
||||
<attr name="fragmentReenterTransition" format="reference"/>
|
||||
|
||||
<!-- Sets whether the enter and exit transitions should overlap when transitioning
|
||||
forward.
|
||||
Corresponds to {@link android.app.Fragment#setAllowEnterTransitionOverlap(
|
||||
boolean)} -->
|
||||
<attr name="fragmentAllowEnterTransitionOverlap" format="reference"/>
|
||||
|
||||
<!-- Sets whether the enter and exit transitions should overlap when transitioning
|
||||
because of popping the back stack.
|
||||
Corresponds to {@link android.app.Fragment#setAllowReturnTransitionOverlap(
|
||||
boolean)} -->
|
||||
<attr name="fragmentAllowReturnTransitionOverlap" format="reference"/>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- Use <code>device-admin</code> as the root tag of the XML resource that
|
||||
|
||||
@@ -2146,7 +2146,7 @@
|
||||
<public type="attr" name="windowExitTransition" />
|
||||
<public type="attr" name="windowSharedElementEnterTransition" />
|
||||
<public type="attr" name="windowSharedElementExitTransition" />
|
||||
<public type="attr" name="windowAllowExitTransitionOverlap" />
|
||||
<public type="attr" name="windowAllowReturnTransitionOverlap" />
|
||||
<public type="attr" name="windowAllowEnterTransitionOverlap" />
|
||||
<public type="attr" name="sessionService" />
|
||||
<public type="attr" name="stackViewStyle" />
|
||||
@@ -2282,6 +2282,14 @@
|
||||
<public type="attr" name="spotShadowAlpha" />
|
||||
<public type="attr" name="navigationIcon" />
|
||||
<public type="attr" name="navigationContentDescription" />
|
||||
<public type="attr" name="fragmentExitTransition" />
|
||||
<public type="attr" name="fragmentEnterTransition" />
|
||||
<public type="attr" name="fragmentSharedElementEnterTransition" />
|
||||
<public type="attr" name="fragmentReturnTransition" />
|
||||
<public type="attr" name="fragmentSharedElementReturnTransition" />
|
||||
<public type="attr" name="fragmentReenterTransition" />
|
||||
<public type="attr" name="fragmentAllowEnterTransitionOverlap" />
|
||||
<public type="attr" name="fragmentAllowReturnTransitionOverlap" />
|
||||
|
||||
<public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
|
||||
|
||||
|
||||
@@ -264,7 +264,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
private Transition mSharedElementReturnTransition = USE_DEFAULT_TRANSITION;
|
||||
private Transition mSharedElementExitTransition = null;
|
||||
private Transition mSharedElementReenterTransition = USE_DEFAULT_TRANSITION;
|
||||
private Boolean mAllowExitTransitionOverlap;
|
||||
private Boolean mAllowReturnTransitionOverlap;
|
||||
private Boolean mAllowEnterTransitionOverlap;
|
||||
private long mBackgroundFadeDurationMillis = -1;
|
||||
private Boolean mSharedElementsUseOverlay;
|
||||
@@ -3549,9 +3549,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
mAllowEnterTransitionOverlap = getWindowStyle().getBoolean(
|
||||
R.styleable.Window_windowAllowEnterTransitionOverlap, true);
|
||||
}
|
||||
if (mAllowExitTransitionOverlap == null) {
|
||||
mAllowExitTransitionOverlap = getWindowStyle().getBoolean(
|
||||
R.styleable.Window_windowAllowExitTransitionOverlap, true);
|
||||
if (mAllowReturnTransitionOverlap == null) {
|
||||
mAllowReturnTransitionOverlap = getWindowStyle().getBoolean(
|
||||
R.styleable.Window_windowAllowReturnTransitionOverlap, true);
|
||||
}
|
||||
if (mBackgroundFadeDurationMillis < 0) {
|
||||
mBackgroundFadeDurationMillis = getWindowStyle().getInteger(
|
||||
@@ -4017,13 +4017,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAllowExitTransitionOverlap(boolean allowExitTransitionOverlap) {
|
||||
mAllowExitTransitionOverlap = allowExitTransitionOverlap;
|
||||
public void setAllowReturnTransitionOverlap(boolean allowExitTransitionOverlap) {
|
||||
mAllowReturnTransitionOverlap = allowExitTransitionOverlap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllowExitTransitionOverlap() {
|
||||
return (mAllowExitTransitionOverlap == null) ? true : mAllowExitTransitionOverlap;
|
||||
public boolean getAllowReturnTransitionOverlap() {
|
||||
return (mAllowReturnTransitionOverlap == null) ? true : mAllowReturnTransitionOverlap;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user