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

VIN
  • 6,385
  • 7
  • 38
  • 77
  • 3
    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 } – uberchilly Oct 30 '20 at 07:52

1 Answers1

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).

ianhanniballake
  • 191,609
  • 30
  • 470
  • 443
  • 1
    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)` – VIN Jan 27 '20 at 06:11
  • I'm launching the BottomSheet via a button on mainActivity `btn_bottom_sheet.setOnClickListener { FragmentOne().show(supportFragmentManager, "appBottomSheet") }` – VIN Jan 27 '20 at 06:12
  • Is there a reason you're manually calling `show()` to show your BottomSheetDialogFragment and not just using the `` 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). – ianhanniballake Jan 27 '20 at 06:33
  • 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? – VIN Jan 29 '20 at 06:28
  • 1
    @ianhanniballake 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. – uberchilly Oct 29 '20 at 21:06