Skip to content

Commit

Permalink
Merge "Fix fragment transitions in new state manager" into androidx-main
Browse files Browse the repository at this point in the history
  • Loading branch information
Treehugger Robot authored and Gerrit Code Review committed Jun 9, 2021
2 parents 84ab1a6 + 06769a5 commit a2adbef
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class FragmentSharedElementTransitionTest {
}

@Test
fun testNestedSharedElementViewNonMatching() {
fun testNestedSharedElementViewsMoreOutViews() {
with(ActivityScenario.launch(FragmentTestActivity::class.java)) {
val fragment = TransitionFragment(R.layout.scene5)
withActivity {
Expand All @@ -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 {
Expand All @@ -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)
}
}
}
37 changes: 37 additions & 0 deletions fragment/fragment/src/androidTest/res/layout/scene6.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright 2021 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sharedElementContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout android:id="@+id/containerBlueSquare"
android:transitionName="blueSquare"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#008">
<View android:id="@+id/greenSquare"
android:transitionName="greenSquare"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#080"/>
<View android:id="@+id/redSquare"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#800"
android:layout_gravity="end"/>
</FrameLayout>
</FrameLayout>
37 changes: 37 additions & 0 deletions fragment/fragment/src/androidTest/res/layout/scene7.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright 2021 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sharedElementContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout android:id="@+id/containerBlueSquare"
android:transitionGroup="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#008">
<View android:id="@+id/greenSquare"
android:transitionName="greenSquare"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#080"/>
<View android:id="@+id/redSquare"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#800"
android:layout_gravity="end"/>
</FrameLayout>
</FrameLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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()) {
Expand All @@ -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()) {
Expand Down Expand Up @@ -700,16 +693,18 @@ void retainMatchingViews(@NonNull ArrayMap<String, View> sharedElementViews,
*/
void captureTransitioningViews(ArrayList<View> 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 {
Expand Down

0 comments on commit a2adbef

Please sign in to comment.