diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentSharedElementTransitionTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentSharedElementTransitionTest.kt
index b3491c79f672b..c0f6bfa7a468a 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentSharedElementTransitionTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentSharedElementTransitionTest.kt
@@ -64,7 +64,7 @@ class FragmentSharedElementTransitionTest {
}
@Test
- fun testNestedSharedElementViewNonMatching() {
+ fun testNestedSharedElementViewsMoreOutViews() {
with(ActivityScenario.launch(FragmentTestActivity::class.java)) {
val fragment = TransitionFragment(R.layout.scene5)
withActivity {
@@ -80,6 +80,11 @@ class FragmentSharedElementTransitionTest {
val redSquare = withActivity { findViewById(R.id.redSquare) }
val startBlueBounds = containerBlueSquare.boundsOnScreen
+ fragment.enterTransition.verifyAndClearTransition {
+ enteringViews += listOf(greenSquare, redSquare)
+ }
+ verifyNoOtherTransitions(fragment)
+
val fragment2 = TransitionFragment(R.layout.scene4)
withActivity {
@@ -93,16 +98,102 @@ class FragmentSharedElementTransitionTest {
val blueSquare = withActivity { findViewById(R.id.blueSquare) }
- fragment.enterTransition.verifyAndClearTransition {
- enteringViews += listOf(containerBlueSquare, greenSquare, redSquare)
+ fragment.exitTransition.verifyAndClearTransition {
+ exitingViews += listOf(greenSquare, redSquare)
+ epicenter = startBlueBounds
}
fragment2.sharedElementEnter.verifyAndClearTransition {
enteringViews += listOf(blueSquare)
- exitingViews += listOf(containerBlueSquare, greenSquare)
+ exitingViews += listOf(containerBlueSquare)
epicenter = startBlueBounds
}
verifyNoOtherTransitions(fragment)
verifyNoOtherTransitions(fragment2)
}
}
+
+ @Test
+ fun testNestedSharedElementViewsMoreInViews() {
+ with(ActivityScenario.launch(FragmentTestActivity::class.java)) {
+ val fragment = TransitionFragment(R.layout.scene4)
+ withActivity {
+ supportFragmentManager
+ .beginTransaction()
+ .setReorderingAllowed(true)
+ .replace(R.id.content, fragment)
+ .commit()
+ }
+
+ val blueSquare = withActivity { findViewById(R.id.blueSquare) }
+ val startBlueBounds = blueSquare.boundsOnScreen
+
+ fragment.enterTransition.verifyAndClearTransition {
+ enteringViews += listOf(blueSquare)
+ }
+ verifyNoOtherTransitions(fragment)
+
+ val fragment2 = TransitionFragment(R.layout.scene6)
+
+ withActivity {
+ supportFragmentManager
+ .beginTransaction()
+ .setReorderingAllowed(true)
+ .addSharedElement(blueSquare, "blueSquare")
+ .replace(R.id.content, fragment2)
+ .commit()
+ }
+
+ val containerBlueSquare = withActivity { findViewById(R.id.containerBlueSquare) }
+
+ fragment2.sharedElementEnter.verifyAndClearTransition {
+ exitingViews += listOf(blueSquare)
+ enteringViews += listOf(containerBlueSquare)
+ epicenter = startBlueBounds
+ }
+ verifyNoOtherTransitions(fragment)
+ verifyNoOtherTransitions(fragment2)
+ }
+ }
+
+ @Test
+ fun testNestedTransitionGroupTrue() {
+ with(ActivityScenario.launch(FragmentTestActivity::class.java)) {
+ val fragment = TransitionFragment(R.layout.scene7)
+ withActivity {
+ supportFragmentManager
+ .beginTransaction()
+ .setReorderingAllowed(true)
+ .replace(R.id.content, fragment)
+ .commit()
+ }
+
+ val containerBlueSquare = withActivity { findViewById(R.id.containerBlueSquare) }
+
+ fragment.enterTransition.verifyAndClearTransition {
+ enteringViews += listOf(containerBlueSquare)
+ }
+ verifyNoOtherTransitions(fragment)
+
+ val fragment2 = TransitionFragment(R.layout.scene4)
+
+ withActivity {
+ supportFragmentManager
+ .beginTransaction()
+ .setReorderingAllowed(true)
+ .replace(R.id.content, fragment2)
+ .commit()
+ }
+
+ val blueSquare = withActivity { findViewById(R.id.blueSquare) }
+
+ fragment.exitTransition.verifyAndClearTransition {
+ exitingViews += listOf(containerBlueSquare)
+ }
+ fragment2.enterTransition.verifyAndClearTransition {
+ enteringViews += listOf(blueSquare)
+ }
+ verifyNoOtherTransitions(fragment)
+ verifyNoOtherTransitions(fragment2)
+ }
+ }
}
diff --git a/fragment/fragment/src/androidTest/res/layout/scene6.xml b/fragment/fragment/src/androidTest/res/layout/scene6.xml
new file mode 100644
index 0000000000000..552ee6f6d7991
--- /dev/null
+++ b/fragment/fragment/src/androidTest/res/layout/scene6.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fragment/fragment/src/androidTest/res/layout/scene7.xml b/fragment/fragment/src/androidTest/res/layout/scene7.xml
new file mode 100644
index 0000000000000..76ad6ee951ebb
--- /dev/null
+++ b/fragment/fragment/src/androidTest/res/layout/scene7.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.java b/fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.java
index 5b2884d5b82c3..20cf2c6c0ff82 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.java
@@ -33,6 +33,7 @@
import androidx.core.util.Preconditions;
import androidx.core.view.OneShotPreDrawListener;
import androidx.core.view.ViewCompat;
+import androidx.core.view.ViewGroupCompat;
import java.util.ArrayList;
import java.util.Collection;
@@ -459,11 +460,7 @@ public void run() {
}
});
- // Capture all views from the firstOut Fragment under the shared element views
- for (View sharedElementView : firstOutViews.values()) {
- captureTransitioningViews(sharedElementFirstOutViews,
- sharedElementView);
- }
+ sharedElementFirstOutViews.addAll(firstOutViews.values());
// Compute the epicenter of the firstOut transition
if (!exitingNames.isEmpty()) {
@@ -473,11 +470,7 @@ public void run() {
firstOutEpicenterView);
}
- // Capture all views from the lastIn Fragment under the shared element views
- for (View sharedElementView : lastInViews.values()) {
- captureTransitioningViews(sharedElementLastInViews,
- sharedElementView);
- }
+ sharedElementLastInViews.addAll(lastInViews.values());
// Compute the epicenter of the lastIn transition
if (!enteringNames.isEmpty()) {
@@ -700,16 +693,18 @@ void retainMatchingViews(@NonNull ArrayMap sharedElementViews,
*/
void captureTransitioningViews(ArrayList transitioningViews, View view) {
if (view instanceof ViewGroup) {
- if (!transitioningViews.contains(view)
- && ViewCompat.getTransitionName(view) != null) {
- transitioningViews.add(view);
- }
ViewGroup viewGroup = (ViewGroup) view;
- int count = viewGroup.getChildCount();
- for (int i = 0; i < count; i++) {
- View child = viewGroup.getChildAt(i);
- if (child.getVisibility() == View.VISIBLE) {
- captureTransitioningViews(transitioningViews, child);
+ if (ViewGroupCompat.isTransitionGroup(viewGroup)) {
+ if (!transitioningViews.contains(view)) {
+ transitioningViews.add(viewGroup);
+ }
+ } else {
+ int count = viewGroup.getChildCount();
+ for (int i = 0; i < count; i++) {
+ View child = viewGroup.getChildAt(i);
+ if (child.getVisibility() == View.VISIBLE) {
+ captureTransitioningViews(transitioningViews, child);
+ }
}
}
} else {