Status Update
Comments
mv...@google.com <mv...@google.com> #2
il...@google.com <il...@google.com> #3
One thought I had was to leverage the reflect
package in Compose
Perhaps you could have a navigation-fragment-compose
artifact that allowed you to add a <composable>
destination to your fragment navigation graph built in XML where the XML would allow you to use the android:name
to define the fully qualified name for the composable function you want to use as your destination.
We could then write a ComposableFragment
class that's sole responsibility is to load that composable function via reflection. Instances of that ComposableFragment
would be what would be added to the NavHostFragment
back stack when you navigate
to that destination.
Effectively, from a developer perspective, you have destinations that are completely implemented as a composable function, but are actually interoperable with a fragment back stack.
This wouldn't give you full access to the Fragment APIs (i.e., you couldn't define what AndroidX Transition your Fragment uses), but if you needed that for a particular destination, you could still create a Fragment that uses ComposeView
directly like you can do today.
ch...@google.com <ch...@google.com> #4
Did a rough prototype of Ian's idea in
- Nav graph:
https://github.com/arriolac/IncrementalNav/blob/main/app/src/main/res/navigation/nav_main.xml ComposeFragment
:https://github.com/arriolac/IncrementalNav/blob/main/app/src/main/java/com/example/incrementalnav/ComposeFragment.kt
Some considerations with this approach:
- Navigating to a screen-level composable to be contained with a
ComposeFragment
would need to provide the composable name and the containing Kotlin file (so you know which Class to do the reflection against). In my prototype, have the composable withinComposeFragment
though in a real-world app you'd have a different structure. - The screen-level composable in my prototype doesn't include any parameters though that would have to be taken into account. As in parameters to the composable need to be passed in via NavBackStackEntry
an...@google.com <an...@google.com> #5
il...@google.com <il...@google.com> #6
Re
ni...@hinge.co <ni...@hinge.co> #7
We are currently incrementally migrating to compose and we have been creating wrapper fragments for our new compose screens which isn't so bad. But one issue is around dialogs and bottom sheets. They cannot be easily migrated because putting the dialog composables inside a dialog fragment creates two dialog windows (one from compose and one from the fragment). For that reason it would be create if we could add composable destinations along side fragment destinations.
mr...@gmail.com <mr...@gmail.com> #8
jb...@google.com <jb...@google.com>
st...@gmail.com <st...@gmail.com> #9
jb...@google.com <jb...@google.com>
ap...@google.com <ap...@google.com> #10
Branch: androidx-main
commit 3792a45bd2a72af6915853bce71f2241843c9b70
Author: Ian Lake <ilake@google.com>
Date: Fri Mar 15 22:33:28 2024
Add project template for navigation-fragment-compose
Use the create_project.py script to create the
navigation-fragment-compose module.
Strips out the multiplatform support as
Navigation with Fragments (which this library extends)
will remain a single platform library.
Relnote: N/A
Test: Compose Studio opens
BUG: 265480755
Change-Id: Ia3dd103c856c470142fd2af40851ccf9a4bc5aa3
M docs-tip-of-tree/build.gradle
A navigation/navigation-fragment-compose/api/current.txt
A navigation/navigation-fragment-compose/api/res-current.txt
A navigation/navigation-fragment-compose/api/restricted_current.txt
A navigation/navigation-fragment-compose/build.gradle
A navigation/navigation-fragment-compose/src/main/java/androidx/navigation/androidx-navigation-navigation-fragment-compose-documentation.md
M settings.gradle
ap...@google.com <ap...@google.com> #11
Branch: androidx-main
commit fca90c019bd25cc72ee9069af5ddbf51d48af99c
Author: Ian Lake <ilake@google.com>
Date: Sat Mar 16 00:02:31 2024
Add ComposableFragment
Create a generic ComposableFragment class that can
load its entire contents from a Composable method
that is given to it via a fully qualified name.
This has some limitations:
- the Composable method must be a static, top-level method
- the Composable method must take no arguments
Relnote: N/A
Test: new ComposableFragmentTest
BUG: 265480755
Change-Id: Ibceff877ee5ef8d4097b1f3e04b51e5d6e6be3eb
M navigation/navigation-fragment-compose/api/current.txt
M navigation/navigation-fragment-compose/api/restricted_current.txt
M navigation/navigation-fragment-compose/build.gradle
A navigation/navigation-fragment-compose/src/androidTest/AndroidManifest.xml
A navigation/navigation-fragment-compose/src/androidTest/java/androidx/navigation/fragment/compose/ComposableFragmentTest.kt
A navigation/navigation-fragment-compose/src/androidTest/java/androidx/navigation/fragment/compose/test/TestActivity.kt
A navigation/navigation-fragment-compose/src/androidTest/res/layout/activity_main.xml
A navigation/navigation-fragment-compose/src/main/java/androidx/navigation/fragment/compose/ComposableFragment.kt
ap...@google.com <ap...@google.com> #12
Branch: androidx-main
commit 15b93a31800c4d1e86fb93ac9a793b7e08b6d892
Author: Ian Lake <ilake@google.com>
Date: Tue Mar 26 20:21:40 2024
Add ComposableFragmentNavigator
Add a Navigator that intercepts the inflation
of composable destinations and rewrites them as
FragmentNavigator.Destination instances that use
ComposableFragment as their implementation, passing
along the class to load via reflection as an
argument.
Relnote: N/A
Test: new ComposableFragmentNavigatorTest
BUG: 265480755
Change-Id: Ic70781f6b2d72f0c2d3ced183b969a708249afc4
M navigation/navigation-fragment-compose/api/current.txt
M navigation/navigation-fragment-compose/api/restricted_current.txt
A navigation/navigation-fragment-compose/src/androidTest/java/androidx/navigation/fragment/compose/ComposableFragmentNavigatorTest.kt
A navigation/navigation-fragment-compose/src/androidTest/res/navigation/nav_simple.xml
M navigation/navigation-fragment-compose/src/main/java/androidx/navigation/fragment/compose/ComposableFragment.kt
A navigation/navigation-fragment-compose/src/main/java/androidx/navigation/fragment/compose/ComposableFragmentNavigator.kt
ap...@google.com <ap...@google.com> #13
Branch: androidx-main
commit b40ba45605bd3af6b2ce01b94e60acb86952f000
Author: Ian Lake <ilake@google.com>
Date: Wed Apr 10 21:19:43 2024
Add ComposableNavHostFragment
Add a convenience extension on NavHostFragment
that automatically adds the
ComposableFragmentNavigator. This ensures that
developers can directly substitute
NavHostFragment for ComposableNavHostFragment in
a layout XML file.
Relnote: "Adds a new `navigation-fragment-compose`
artifact that includes a `ComposableNavHostFragment`
alternative to `NavHostFragment` that allows you to
add `composable` destinations to your Navigation XML
files. Each `composable` destination must be
expressed as a top-level, no argument `@Composable`
method whose fully qualified name is used as the
`android:name` attribute on each destination. When
navigating to one of these destinations, a containing
fragment is created to display the composable content."
BUG: 265480755
Test: new ComposableNavHostFragmentTest
Change-Id: I0ef2e5897128d18d1b374f3617c7095022ca7c0e
M navigation/navigation-fragment-compose/api/current.txt
M navigation/navigation-fragment-compose/api/restricted_current.txt
A navigation/navigation-fragment-compose/src/androidTest/java/androidx/navigation/fragment/compose/ComposableNavHostFragmentTest.kt
A navigation/navigation-fragment-compose/src/main/java/androidx/navigation/fragment/compose/ComposableNavHostFragment.kt
ap...@google.com <ap...@google.com> #14
Branch: androidx-main
commit 261c755a06f74528077df263d847cfa2657ff89e
Author: Ian Lake <ilake@google.com>
Date: Fri Apr 12 21:07:39 2024
Add LocalFragment to navigation-fragment-compose
Add a composition local that allows a composable
method inside a ComposableFragment to access the
Fragment instance.
This allows the method to extract arguments,
set transitions on the Fragment instance, and
otherwise avoid cases where you'd manually need
to construct a Fragment with a ComposeView as
its view just to access Fragment related properties.
Relnote: "The `navigation-fragment-compose` artifact
now provides a `LocalFragment` composition local to
composable methods within a `ComposableFragment`."
BUG: 265480755
Test: new ComposableFragmentTest added
Change-Id: If35e5405bbd94fd5f45c1cc0dfe3d74278d64a09
M navigation/navigation-fragment-compose/api/current.txt
M navigation/navigation-fragment-compose/api/restricted_current.txt
M navigation/navigation-fragment-compose/src/androidTest/java/androidx/navigation/fragment/compose/ComposableFragmentTest.kt
M navigation/navigation-fragment-compose/src/main/java/androidx/navigation/fragment/compose/ComposableFragment.kt
A navigation/navigation-fragment-compose/src/main/java/androidx/navigation/fragment/compose/LocalFragment.kt
ca...@gmail.com <ca...@gmail.com> #15
why it is not possible to pass de backStackEntry to the composable function in order to get the some arguments inside the composable function?. This feature is very nice but it solves only a part of the problem, the majority of destinations have arguments being passed down.
il...@google.com <il...@google.com> #16
Re LocalFragment
, you'll see retrieving arguments is exactly the use case for that API using LocalFragment.current.requireArguments()
je...@pinkfroot.com <je...@pinkfroot.com> #17
Is there a way to make this work with the Safe Args plugin? As soon as I add an action
to a composable
destination like so:
<composable
android:id="@+id/home_screen"
android:name="com.example.HomeScreenKt\$HomeScreen" >
<action
android:id="@+id/action_home_screen_to_other_fragment"
app:destination="@id/other_fragment" />
</composable>
My project build fails on the :app:generateSafeArgs
task with the following error:
Can't escape identifier `HomeScreenKt\$HomeScreenDirections` because it contains illegal characters: \
il...@google.com <il...@google.com> #18
Re
Description
Component used: Navigation Version used: 2.5.3
Use Case
I would like to be able to incrementally migrate to Navigation Compose while migrating a Fragment View-based app to Compose.
Problem Statement
When migrating a Fragment View-based app that is using Navigation Component to Compose, it's not currently possible to incrementally migrate to Navigation Compose. Instead, all screens first need to be migrated to Compose and only then can apps migrate to Navigation Compose.
While this might work for smaller apps, this may not be feasible for apps with a lot of screens as the switch would be a pretty large change all at once. Additionally, new features or screens would still need to be wrapped inside a Fragment which is tech debt as the eventual goal is to remove fragments altogether. This experience can be improved by creating better interop between Fragment and Compose Navigation.
Possible Solution
Add a single Compose container fragment in the navigation graph. This container can then add new composable destinations to the existing XML navigation graph. This would also avoid new screens having to create new fragments altogether and migrated screens (composables) can then be incrementally added to the graph. Once all screens are in Compose, the switch to remove Fragment-based navigation should be a smaller change.