NavigationComponent navigation within a BottomSheetDialogFragment
F

1

13

Can Android's Navigation Component be used for navigation WITHIN a BottomSheet (i.e. replacing/adding fragments within a single bottom sheet)?

I know how to launch a BottomSheetDialogFragment using the <dialog> tag within a Navigation Graph. For example, the below nav_graph.xml allows the user to navigate from one BottomSheetDialogFragment (fragmentOne) to another BottomSheetDialogFragment (fragmentTwo). FragmentTwo opens as a second BottomSheet over FragmentOne's BottomSheet.

However, what if I wanted fragmentTwo to replace fragmentOne WITHIN THE SAME BottomSheet? How would I accomplish this using the Navigation Graph?

<navigation android:id="@+id/nav_graph"
        app:startDestination="@id/fragmentOne">

    <dialog android:id="@+id/fragmentOne"
        android:name="com.example.navcomponentapp.FragmentOne"
        android:label="fragment_fragment_one"
        tools:layout="@layout/fragment_fragment_one">

        <action android:id="@+id/action_fragmentOne_to_fragmentTwo2"
            app:destination="@id/fragmentTwo"/>
    </dialog>

    <dialog android:id="@+id/fragmentTwo"
        android:name="com.example.navcomponentapp.FragmentTwo"
        android:label="fragment_fragment_two"
        tools:layout="@layout/fragment_fragment_two"/>
</navigation>

Demo (this is not what I want. I don't want a bottomSheet opening over another bottomSheet

Figurant answered 27/1, 2020 at 1:47 Comment(1)
I also had to do this for the back to work dialog.setOnKeyListener { arg0, keyCode, event -> if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) { if (!navController.navigateUp()) { dialog.dismiss() true } true } true }Clyte
R
9

A NavHostFragment is the container that gets its contents replaced. Therefore, if you want to have a container within your BottomSheetDialogFragment that is separate from the outer NavHostFragment's container (i.e., the container that is ~the whole content of your activity), you'd want to add a separate NavHostFragment within the layout of your BottomSheetDialogFragment with its own navigation graph.

Then navigating within that smaller container would only replace the contents within the bottom sheet (and you'd use requireParentFragment().findNavController() to access the outer NavController if you wanted to do a navigate() operation at the outer level).

Receptive answered 27/1, 2020 at 4:53 Comment(5)
Thanks! I was able to get it to work with your suggestions. When I launch the BottomSheet the first time, it works. When I try to launch the BottomSheet a second time, I get Caused by: java.lang.IllegalArgumentException: Binary XML file line #8: Duplicate id 0x7f080095, tag null, or parent id 0xffffffff with another fragment for androidx.navigation.fragment.NavHostFragment at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:116)Figurant
I'm launching the BottomSheet via a button on mainActivity btn_bottom_sheet.setOnClickListener { FragmentOne().show(supportFragmentManager, "appBottomSheet") }Figurant
Is there a reason you're manually calling show() to show your BottomSheetDialogFragment and not just using the <dialog> destination to show your dialog? Make sure you're not using the same android:id in multiple places (your outer NavHostFragment shouldn't have the same id as the inner one).Receptive
The reason I'm using show() is because I'm experimenting using the Navigation Component starting with the bottomSheet as a nav host without the need to have an activity as a the starting nav host. Do you know if thIs is possible?Figurant
@Receptive is there a way to deeplink into the destion of this inner nav host in bottom sheet? Maybe deep link via uri? Similar use case is when we have bottom nav inside one of the fragments. This also requires additional nav host.Clyte

© 2022 - 2024 — McMap. All rights reserved.