Status Update
Comments
il...@google.com <il...@google.com> #2
Branch: androidx-main
commit 6856d4b8fe5fbd6d5d2926ca6ced38f286751505
Author: Ralston Da Silva <ralu@google.com>
Date: Wed Aug 17 12:53:32 2022
Renaming focusDirections In & Out to Enter & Exit
We want to add custom focus properties for In & Out,
but we can't do that since in is a reserved keyword in kotlin.
This CL renames the In and Out focus directions to Enter and Exit.
Bug: 183746982
Test: ./gradlew compose:ui:ui:cC -P android.testInstrumentationRunnerArguments.class=androidx.compose.ui.focus.TwoDimensionalFocusTraversalEnterTest
Test: ./gradlew compose:ui:ui:cC -P android.testInstrumentationRunnerArguments.class=androidx.compose.ui.focus.TwoDimensionalFocusTraversalEnterTest
Relnote: Renamed FocusDirection.In and FocusDirection.Out to FocusDirection.Enter and FocusDirection.Exit
Change-Id: Ia4262d2f8edc3ec36d2edc9ed2858895971ba33c
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusTraversalExitTest.kt
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FocusSearchNonPlacedItemsTest.kt
M compose/ui/ui/api/restricted_current.ignore
M compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/FocusGroupTest.kt
M compose/ui/ui/api/current.txt
M compose/ui/ui/api/1.3.0-beta02.txt
M compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTraversal.kt
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusTraversalEnterTest.kt
M compose/ui/ui/api/current.ignore
M compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
M compose/ui/ui/api/public_plus_experimental_1.3.0-beta02.txt
M compose/ui/ui/api/restricted_1.3.0-beta02.txt
M compose/ui/ui/api/restricted_current.txt
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/KeyEventToFocusDirectionTest.kt
M compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOrderModifier.kt
M compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListFocusMoveTest.kt
M compose/ui/ui/api/public_plus_experimental_current.txt
il...@google.com <il...@google.com> #3
Branch: androidx-main
commit 8bbfa2fd7f3cb0f386c186b5df840513d8246d6b
Author: Ralston Da Silva <ralu@google.com>
Date: Mon Aug 29 16:16:07 2022
Added custom focus properties for enter and exit
Added experimental API for users to specify a custom enter and exit
behavior when focus enters/exits a focus group.
Bug: 183746982
Relnote: "Added experimental API for users to specify a custom enter and exit behavior when focus enters/exits a focus group."
Test: ./gradlew compose:ui:ui:cC -P android.testInstrumentationRunnerArguments.class=androidx.compose.ui.focus.TwoDimensionalFocusTraversalEnterTest
Test: ./gradlew compose:ui:ui:cC -P android.testInstrumentationRunnerArguments.class=androidx.compose.ui.focus.TwoDimensionalFocusTraversalExitTest
Change-Id: I5f3f9e1c20494f3ee0d6484854c3d50485422ba3
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusTraversalExitTest.kt
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusTraversalTest.kt
M compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTraversal.kt
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusTraversalInitialFocusTest.kt
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusTraversalEnterTest.kt
M compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusProperties.kt
M compose/ui/ui/api/public_plus_experimental_1.3.0-beta02.txt
M compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/FocusSamples.kt
M compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOrderModifier.kt
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FocusTestUtils.kt
M compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusSearch.kt
M compose/ui/ui/api/public_plus_experimental_current.txt
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/CustomFocusTraversalTest.kt
il...@google.com <il...@google.com> #4
Branch: androidx-main
commit d496b3e091b18ddb0c179803ef1504ce5a715cc4
Author: Ralston Da Silva <ralu@google.com>
Date: Thu Sep 01 01:27:59 2022
Add support for implicit focus enter and exit
We perform an implicit Enter in the following cases:
1. The user calls requestFocus() on a focus group.
2. The user navigates to a focus group during focus search.
We perform an implicit Exit in the following case:
1. The user reaches the end of a focus group and
focus search takes the user outside the focus group.
Bug: 183746982
Fix: 183746982
Test: ./gradlew compose:ui:ui:cC -P android.testInstrumentationRunnerArguments.class=androidx.compose.ui.focus.TwoDimensionalFocusTraversalImplicitEnterTest
Test: ./gradlew compose:ui:ui:cC -P android.testInstrumentationRunnerArguments.class=androidx.compose.ui.focus.TwoDimensionalFocusTraversalImplicitExitTest
Change-Id: Ibd1b28c6e401490e72dc232f166449f0a6e34e10
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusTraversalExitTest.kt
A compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusTraversalImplicitExitTest.kt
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FocusRequesterTest.kt
A compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusTraversalImplicitEnterTest.kt
M compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/UiDemos.kt
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusTraversalTest.kt
M compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequester.kt
A compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/focus/ExplicitEnterExitWithCustomFocusEnterExitDemo.kt
M compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTransactions.kt
M compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusSearch.kt
il...@google.com <il...@google.com> #5
This bug was linked in a change in the following release(s):
androidx.compose.foundation:foundation:1.3.0-beta02
il...@google.com <il...@google.com>
ap...@google.com <ap...@google.com> #6
This bug was linked in a change in the following release(s):
androidx.compose.ui:ui:1.3.0-beta03
ap...@google.com <ap...@google.com> #7
androidx.compose.ui:ui:1.3.0-beta03androidx.compose.foundation6856d4b8fe5fbd6d5d2926ca6ced38f286751505release(s):
androidx.compose.foundation:foundation:1.3.0-beta02elease(s):
androidx.compose.foundation:foundation:1.3.0-beta02
ap...@google.com <ap...@google.com> #8
Branch: androidx-main
commit 9ad171525dfbb4a5393538a87f32567bcc2f4960
Author: Ian Lake <ilake@google.com>
Date: Thu Mar 18 22:14:33 2021
Remove fragments inflated from AndroidViewBinding
When an AndroidViewBinding is disposed, it is
responsible for cleaning up its state. Unlike
regular views, any fragments inflated from a
FragmentContainerView must be manually cleaned
by removing them from the FragmentManager.
This avoids cases where repeatedly adding and
removing an AndroidViewBinding from the hierarchy
creates more and more fragment instances or
re-uses fragment instances with state that should
have been disposed of with the containing composable.
Relnote: "`AndroidViewBinding` now properly removes
fragments inflated via `FragmentContainerView` when
the `AndroidViewBinding` is removed from the compose
hierarchy."
Test: FragmentRemoveTest suite
BUG: 179915946
Change-Id: Ib02480f78570972b3190ebd45ab12f4d7291fa23
M compose/ui/ui-viewbinding/build.gradle
M compose/ui/ui-viewbinding/samples/src/androidTest/AndroidManifest.xml
A compose/ui/ui-viewbinding/samples/src/androidTest/java/androidx/compose/ui/samples/FragmentRemoveTest.kt
M compose/ui/ui-viewbinding/src/main/java/androidx/compose/ui/viewinterop/AndroidViewBinding.kt
il...@google.com <il...@google.com> #9
Verified with a androidx.compose.ui:ui-viewbinding:1.0.0-SNAPSHOT
with build 7236835
fixes all of the issues in the above FragmentInCompose
app.
This means that you can use AndroidViewBinding
directly with layouts that inflate fragments via FragmentContainerView
. I'd suggest inflating fragments into your Compose hierarchy only as a transitional step and not as a suggested final architecture. :-)
Note: the <fragment>
tag should never be used in any app, much less an app built on Compose. It is expected that inflating the same <fragment>
layout twice will still crash your app.
sn...@gmail.com <sn...@gmail.com> #10
is this issue really resolved ?
I still face the same issue .
Here is my code , is there anything I am missing out ?
Scaffold(topBar = { TopAppBar(topAppBarData = topBar) })
{
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
AndroidViewBinding(TestFragmentBinding::inflate)
}
}
il...@google.com <il...@google.com> #11
Re
ro...@theorytank.com <ro...@theorytank.com> #12
I think the problem is that the onRelease code assumes that the localContext (see --->) can be cast to an Activity. But this doesn't work when it's a ContextThemeWrapper.
onRelease = { view ->
view.getBinding<T>().onRelease()
(view as? ViewGroup)?.let { rootGroup ->
// clean up inflated fragments when the AndroidViewBinding is disposed
// Find the right FragmentManager
val fragmentManager = parentFragment?.childFragmentManager
---> ?: (localContext as? FragmentActivity)?.supportFragmentManager
forEachFragmentContainerView(rootGroup) { container ->
// Now find the fragment inflated via the FragmentContainerView
val existingFragment = fragmentManager?.findFragmentById(container.id)
if (existingFragment != null && !fragmentManager.isStateSaved) {
// If the state isn't saved, that means that some state change
// has removed this Composable from the hierarchy
fragmentManager.commitNow {
remove(existingFragment)
}
}
}
}
},
il...@google.com <il...@google.com> #13
Re AndroidFragment
fragment-compose
artifact, which is what we suggest for embedding your fragment in a Compose hierarchy now.
[Deleted User] <[Deleted User]> #14
Re
Description
Jetpack Compose release version: Compose alpha11 Android Studio Build: Arctic Fox Canary 4
There appears to be a number of issues with inflating a fragment by using
AndroidViewBinding
:If you use
FragmentContainerView
, the fragment appears the first time the container is inflated, but later times it does not appear.If you use
<fragment>
, the fragment appears the first time the fragment is inflated, but will crash if you try to re-inflate the same layout a second time. Rotating your screen or otherwise recreating the Activity will reset it so that the first inflation worksIn both cases, removing the
AndroidViewBinding
from your compose hierarchy does not remove the underlyingFragment
from theFragmentManager
. This means that the Fragment remains in memory forever afterwards.I've attached a sample project that contains three situation (using
FragmentContainerView
, using<fragment>
, and manually doing aFragmentTransaction
in Compose code) and a 'Show' button of each that lets you confirm what happens when theAndroidViewBinding
is removed from the hierarchy.My investigation lead to a couple of discoveries:
After a configuration change, the whole activity and the
FragmentManager
has moved to theRESUMED
state before the compose hierarchy is processed andAndroidViewBinding
is able to inflate its container. This means the original fragment added via the inflatedFragmentContainerView
has already had its view created and moved to theRESUMED
state before the container exists. Thus, the transition betweenonCreateView()
andonViewCreated()
where the view is attached to its container has already passed when theAndroidViewBinding
creates the container.The
<fragment>
tag added fragment never goes above theCREATED
state on its own - Fragments is correctly stopping it from going higher thanCREATED
during the inflation, but because Compose is inflating it after the FragmentManager has already moved throughRESUMED
, the usual moving of state for<fragment>
inflated fragments doesn't happen. Doing anotherFragmentTransaction
on a different fragment/container moves it toSTARTED
, but it never moves toRESUMED
as no FragmentTransactions on that container are pending (and moving toRESUMED
is done at a container by container basis) as the<fragment>
tag doesn't actually do aFragmentTransaction
.It is expected that when a composable is removed from the hierarchy that any internal state is thrown out (that's why you'd normally hoist state you want to save). Because Fragments are never removed when the
AndroidViewBinding
is removed from the hierarchy, the Fragments keep their state over a removal / addition of a new element that happens to inflate that same layout.