Source code
package android.support.v4.app;
import android.graphics.Rect;
import android.transition.Transition;
import android.transition.Transition.EpicenterCallback;
import android.transition.TransitionManager;
import android.transition.TransitionSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver.OnPreDrawListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
class FragmentTransitionCompat21 {
public static class EpicenterView {
public View epicenter;
}
public interface ViewRetriever {
View getView();
}
FragmentTransitionCompat21() {
}
public static String getTransitionName(View view) {
return view.getTransitionName();
}
public static Object cloneTransition(Object transition) {
if (transition != null) {
return ((Transition) transition).clone();
}
return transition;
}
public static Object captureExitingViews(Object exitTransition, View root, ArrayList<View> viewList, Map<String, View> namedViews, View nonExistentView) {
if (exitTransition == null) {
return exitTransition;
}
captureTransitioningViews(viewList, root);
if (namedViews != null) {
viewList.removeAll(namedViews.values());
}
if (viewList.isEmpty()) {
return null;
}
viewList.add(nonExistentView);
addTargets((Transition) exitTransition, viewList);
return exitTransition;
}
public static void excludeTarget(Object transitionObject, View view, boolean exclude) {
((Transition) transitionObject).excludeTarget(view, exclude);
}
public static void beginDelayedTransition(ViewGroup sceneRoot, Object transitionObject) {
TransitionManager.beginDelayedTransition(sceneRoot, (Transition) transitionObject);
}
public static void setEpicenter(Object transitionObject, View view) {
Transition transition = (Transition) transitionObject;
final Rect epicenter = getBoundsOnScreen(view);
transition.setEpicenterCallback(new EpicenterCallback() {
public Rect onGetEpicenter(Transition transition) {
return epicenter;
}
});
}
public static Object wrapSharedElementTransition(Object transitionObj) {
if (transitionObj == null) {
return null;
}
Transition transition = (Transition) transitionObj;
if (transition == null) {
return null;
}
Object transitionSet = new TransitionSet();
transitionSet.addTransition(transition);
return transitionSet;
}
public static void addTransitionTargets(Object enterTransitionObject, Object sharedElementTransitionObject, View container, ViewRetriever inFragment, View nonExistentView, EpicenterView epicenterView, Map<String, String> nameOverrides, ArrayList<View> enteringViews, Map<String, View> namedViews, Map<String, View> renamedViews, ArrayList<View> sharedElementTargets) {
if (enterTransitionObject != null || sharedElementTransitionObject != null) {
final Transition enterTransition = (Transition) enterTransitionObject;
if (enterTransition != null) {
enterTransition.addTarget(nonExistentView);
}
if (sharedElementTransitionObject != null) {
setSharedElementTargets(sharedElementTransitionObject, nonExistentView, namedViews, sharedElementTargets);
}
if (inFragment != null) {
final View view = container;
final View view2 = nonExistentView;
final ViewRetriever viewRetriever = inFragment;
final Map<String, String> map = nameOverrides;
final Map<String, View> map2 = renamedViews;
final ArrayList<View> arrayList = enteringViews;
container.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
public boolean onPreDraw() {
view.getViewTreeObserver().removeOnPreDrawListener(this);
if (enterTransition != null) {
enterTransition.removeTarget(view2);
}
View fragmentView = viewRetriever.getView();
if (fragmentView != null) {
if (!map.isEmpty()) {
FragmentTransitionCompat21.findNamedViews(map2, fragmentView);
map2.keySet().retainAll(map.values());
for (Entry<String, String> entry : map.entrySet()) {
View view = (View) map2.get((String) entry.getValue());
if (view != null) {
view.setTransitionName((String) entry.getKey());
}
}
}
if (enterTransition != null) {
FragmentTransitionCompat21.captureTransitioningViews(arrayList, fragmentView);
arrayList.removeAll(map2.values());
arrayList.add(view2);
FragmentTransitionCompat21.addTargets(enterTransition, arrayList);
}
}
return true;
}
});
}
setSharedElementEpicenter(enterTransition, epicenterView);
}
}
public static Object mergeTransitions(Object enterTransitionObject, Object exitTransitionObject, Object sharedElementTransitionObject, boolean allowOverlap) {
boolean overlap = true;
Transition enterTransition = (Transition) enterTransitionObject;
Transition exitTransition = (Transition) exitTransitionObject;
Transition sharedElementTransition = (Transition) sharedElementTransitionObject;
if (!(enterTransition == null || exitTransition == null)) {
overlap = allowOverlap;
}
if (overlap) {
Transition transitionSet = new TransitionSet();
if (enterTransition != null) {
transitionSet.addTransition(enterTransition);
}
if (exitTransition != null) {
transitionSet.addTransition(exitTransition);
}
if (sharedElementTransition != null) {
transitionSet.addTransition(sharedElementTransition);
}
return transitionSet;
}
Transition staggered = null;
if (exitTransition != null && enterTransition != null) {
staggered = new TransitionSet().addTransition(exitTransition).addTransition(enterTransition).setOrdering(1);
} else if (exitTransition != null) {
staggered = exitTransition;
} else if (enterTransition != null) {
staggered = enterTransition;
}
if (sharedElementTransition == null) {
return staggered;
}
Transition together = new TransitionSet();
if (staggered != null) {
together.addTransition(staggered);
}
together.addTransition(sharedElementTransition);
return together;
}
public static void setSharedElementTargets(Object transitionObj, View nonExistentView, Map<String, View> namedViews, ArrayList<View> sharedElementTargets) {
TransitionSet transition = (TransitionSet) transitionObj;
sharedElementTargets.clear();
sharedElementTargets.addAll(namedViews.values());
List<View> views = transition.getTargets();
views.clear();
int count = sharedElementTargets.size();
for (int i = 0; i < count; i++) {
bfsAddViewChildren(views, (View) sharedElementTargets.get(i));
}
sharedElementTargets.add(nonExistentView);
addTargets(transition, sharedElementTargets);
}
private static void bfsAddViewChildren(List<View> views, View startView) {
int startIndex = views.size();
if (!containedBeforeIndex(views, startView, startIndex)) {
views.add(startView);
for (int index = startIndex; index < views.size(); index++) {
View view = (View) views.get(index);
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
int childCount = viewGroup.getChildCount();
for (int childIndex = 0; childIndex < childCount; childIndex++) {
View child = viewGroup.getChildAt(childIndex);
if (!containedBeforeIndex(views, child, startIndex)) {
views.add(child);
}
}
}
}
}
}
private static boolean containedBeforeIndex(List<View> views, View view, int maxIndex) {
for (int i = 0; i < maxIndex; i++) {
if (views.get(i) == view) {
return true;
}
}
return false;
}
private static void setSharedElementEpicenter(Transition transition, final EpicenterView epicenterView) {
if (transition != null) {
transition.setEpicenterCallback(new EpicenterCallback() {
private Rect mEpicenter;
public Rect onGetEpicenter(Transition transition) {
if (this.mEpicenter == null && epicenterView.epicenter != null) {
this.mEpicenter = FragmentTransitionCompat21.getBoundsOnScreen(epicenterView.epicenter);
}
return this.mEpicenter;
}
});
}
}
private static Rect getBoundsOnScreen(View view) {
Rect epicenter = new Rect();
int[] loc = new int[2];
view.getLocationOnScreen(loc);
epicenter.set(loc[0], loc[1], loc[0] + view.getWidth(), loc[1] + view.getHeight());
return epicenter;
}
private static void captureTransitioningViews(ArrayList<View> transitioningViews, View view) {
if (view.getVisibility() != 0) {
return;
}
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
if (viewGroup.isTransitionGroup()) {
transitioningViews.add(viewGroup);
return;
}
int count = viewGroup.getChildCount();
for (int i = 0; i < count; i++) {
captureTransitioningViews(transitioningViews, viewGroup.getChildAt(i));
}
return;
}
transitioningViews.add(view);
}
public static void findNamedViews(Map<String, View> namedViews, View view) {
if (view.getVisibility() == 0) {
String transitionName = view.getTransitionName();
if (transitionName != null) {
namedViews.put(transitionName, view);
}
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
int count = viewGroup.getChildCount();
for (int i = 0; i < count; i++) {
findNamedViews(namedViews, viewGroup.getChildAt(i));
}
}
}
}
public static void cleanupTransitions(View sceneRoot, View nonExistentView, Object enterTransitionObject, ArrayList<View> enteringViews, Object exitTransitionObject, ArrayList<View> exitingViews, Object sharedElementTransitionObject, ArrayList<View> sharedElementTargets, Object overallTransitionObject, ArrayList<View> hiddenViews, Map<String, View> renamedViews) {
final Transition enterTransition = (Transition) enterTransitionObject;
final Transition exitTransition = (Transition) exitTransitionObject;
final Transition sharedElementTransition = (Transition) sharedElementTransitionObject;
final Transition overallTransition = (Transition) overallTransitionObject;
if (overallTransition != null) {
final View view = sceneRoot;
final ArrayList<View> arrayList = enteringViews;
final ArrayList<View> arrayList2 = exitingViews;
final ArrayList<View> arrayList3 = sharedElementTargets;
final Map<String, View> map = renamedViews;
final ArrayList<View> arrayList4 = hiddenViews;
final View view2 = nonExistentView;
sceneRoot.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
public boolean onPreDraw() {
view.getViewTreeObserver().removeOnPreDrawListener(this);
if (enterTransition != null) {
FragmentTransitionCompat21.removeTargets(enterTransition, arrayList);
}
if (exitTransition != null) {
FragmentTransitionCompat21.removeTargets(exitTransition, arrayList2);
}
if (sharedElementTransition != null) {
FragmentTransitionCompat21.removeTargets(sharedElementTransition, arrayList3);
}
for (Entry<String, View> entry : map.entrySet()) {
((View) entry.getValue()).setTransitionName((String) entry.getKey());
}
int numViews = arrayList4.size();
for (int i = 0; i < numViews; i++) {
overallTransition.excludeTarget((View) arrayList4.get(i), false);
}
overallTransition.excludeTarget(view2, false);
return true;
}
});
}
}
public static void removeTargets(Object transitionObject, ArrayList<View> views) {
Transition transition = (Transition) transitionObject;
int i;
if (transition instanceof TransitionSet) {
TransitionSet set = (TransitionSet) transition;
int numTransitions = set.getTransitionCount();
for (i = 0; i < numTransitions; i++) {
removeTargets(set.getTransitionAt(i), views);
}
} else if (!hasSimpleTarget(transition)) {
List<View> targets = transition.getTargets();
if (targets != null && targets.size() == views.size() && targets.containsAll(views)) {
for (i = views.size() - 1; i >= 0; i--) {
transition.removeTarget((View) views.get(i));
}
}
}
}
public static void addTargets(Object transitionObject, ArrayList<View> views) {
Transition transition = (Transition) transitionObject;
int i;
if (transition instanceof TransitionSet) {
TransitionSet set = (TransitionSet) transition;
int numTransitions = set.getTransitionCount();
for (i = 0; i < numTransitions; i++) {
addTargets(set.getTransitionAt(i), views);
}
} else if (!hasSimpleTarget(transition) && isNullOrEmpty(transition.getTargets())) {
int numViews = views.size();
for (i = 0; i < numViews; i++) {
transition.addTarget((View) views.get(i));
}
}
}
private static boolean hasSimpleTarget(Transition transition) {
return (isNullOrEmpty(transition.getTargetIds()) && isNullOrEmpty(transition.getTargetNames()) && isNullOrEmpty(transition.getTargetTypes())) ? false : true;
}
private static boolean isNullOrEmpty(List list) {
return list == null || list.isEmpty();
}
}