summaryrefslogtreecommitdiffstats
path: root/v4/api21/android
diff options
context:
space:
mode:
authorGeorge Mount <mount@google.com>2015-06-15 12:44:15 -0700
committerGeorge Mount <mount@google.com>2015-06-15 12:44:15 -0700
commitc33885b865c99ce9ae96214f0e9d7bd1ca12cb93 (patch)
tree73cb5944f7e1fcedd46d2b94dd8d98738b91ed36 /v4/api21/android
parent8b6062d084e75466ace36485004193f6a68fbc59 (diff)
downloadandroid_frameworks_support-c33885b865c99ce9ae96214f0e9d7bd1ca12cb93.tar.gz
android_frameworks_support-c33885b865c99ce9ae96214f0e9d7bd1ca12cb93.tar.bz2
android_frameworks_support-c33885b865c99ce9ae96214f0e9d7bd1ca12cb93.zip
Limit shared element transition to shared elements and children.
Bug 20257189 Shared element transitions should target the shared elements or their children. When no target is given to a transition, the transition should target the shared element. If a target is given, it should also be able to target the children of the shared element. This is solved by wrapping the shared element transition with a TransitionSet. The set is given the targets of all shared elements and their children. Further, if no target is given for a transition, the transition is given only the shared elements as targets. Change-Id: I4c13c849898b89c60d9bc0a8dd34d7c5543f2bdc
Diffstat (limited to 'v4/api21/android')
-rw-r--r--v4/api21/android/support/v4/app/FragmentTransitionCompat21.java77
1 files changed, 75 insertions, 2 deletions
diff --git a/v4/api21/android/support/v4/app/FragmentTransitionCompat21.java b/v4/api21/android/support/v4/app/FragmentTransitionCompat21.java
index f88d764a1e..45f67a2518 100644
--- a/v4/api21/android/support/v4/app/FragmentTransitionCompat21.java
+++ b/v4/api21/android/support/v4/app/FragmentTransitionCompat21.java
@@ -79,6 +79,19 @@ class FragmentTransitionCompat21 {
});
}
+ public static Object wrapSharedElementTransition(Object transitionObj) {
+ if (transitionObj == null) {
+ return null;
+ }
+ Transition transition = (Transition) transitionObj;
+ if (transition == null) {
+ return null;
+ }
+ TransitionSet transitionSet = new TransitionSet();
+ transitionSet.addTransition(transition);
+ return transitionSet;
+ }
+
/**
* 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,
@@ -102,8 +115,8 @@ class FragmentTransitionCompat21 {
enterTransition.addTarget(nonExistentView);
}
if (sharedElementTransitionObject != null) {
- Transition sharedElementTransition = (Transition) sharedElementTransitionObject;
- addTargets(sharedElementTransition, sharedElementTargets);
+ setSharedElementTargets(sharedElementTransitionObject, nonExistentView,
+ renamedViews, sharedElementTargets);
}
if (inFragment != null) {
@@ -201,7 +214,67 @@ class FragmentTransitionCompat21 {
return transition;
}
+ /**
+ * Finds all children of the shared elements and sets the wrapping TransitionSet
+ * targets to point to those. It also limits transitions that have no targets to the
+ * specific shared elements. This allows developers to target child views of the
+ * shared elements specifically, but this doesn't happen by default.
+ */
+ 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());
+ final List<View> views = transition.getTargets();
+ views.clear();
+ final int count = sharedElementTargets.size();
+ for (int i = 0; i < count; i++) {
+ final View view = sharedElementTargets.get(i);
+ bfsAddViewChildren(views, view);
+ }
+ sharedElementTargets.add(nonExistentView);
+ addTargets(transition, sharedElementTargets);
+ }
+
+ /**
+ * Uses a breadth-first scheme to add startView and all of its children to views.
+ * It won't add a child if it is already in views.
+ */
+ private static void bfsAddViewChildren(final List<View> views, final View startView) {
+ final int startIndex = views.size();
+ if (containedBeforeIndex(views, startView, startIndex)) {
+ return; // This child is already in the list, so all its children are also.
+ }
+ views.add(startView);
+ for (int index = startIndex; index < views.size(); index++) {
+ final View view = views.get(index);
+ if (view instanceof ViewGroup) {
+ ViewGroup viewGroup = (ViewGroup) view;
+ final int childCount = viewGroup.getChildCount();
+ for (int childIndex = 0; childIndex < childCount; childIndex++) {
+ final View child = viewGroup.getChildAt(childIndex);
+ if (!containedBeforeIndex(views, child, startIndex)) {
+ views.add(child);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Does a linear search through views for view, limited to maxIndex.
+ */
+ private static boolean containedBeforeIndex(final List<View> views, final View view,
+ final 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) {