My app currently uses a navigation host (Android Architecture Components navigation) to switch between fragments. One of these fragments is a more complex form where I want to show/hide some content depending on whether button 1
or button 2
is pressed.
Here is a sketch of it:
How is that normally done in Android? Would I add a second navhost inside of the (blue background) fragment which itself is shown in a nav host? I am also using data binding, would I then have to use a second binding object for the fragments inside the second navhost or could they share a binding object with the "main" (blue background) fragment?
Or would it be better to just manually inflate the two fragments (the one for button1 and the one for button2)? But then, what would I use as container to host them?
Since you use the Navigation components for the main navigation, from a "clean architecture" point of view, it's desirable to use them for the navigation between the child Fragment
s as well.
You can have a NavHostFragment
inside a Fragment
. The important thing is to not set app:defaultNavHost="true"
this time.
My sample app has a FragmentB
with two children FragmentB1
and FragmentB2
.
<androidx.fragment.app.FragmentContainerView
android:id="@+id/childNavHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@+id/toggleGroup"
app:layout_constraintVertical_bias="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:navGraph="@navigation/child_navigation" />
child_navigation.xml
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/chlld__navigation.xml"
app:startDestination="@+id/dest_fragment_b1">
<fragment
android:id="@+id/dest_fragment_b1"
android:name="com.example.nestednavhostfragment.FragmentB1"
android:label="FragmentB1" />
<fragment
android:id="@+id/dest_fragment_b2"
android:name="com.example.nestednavhostfragment.FragmentB2"
android:label="FragmentB2" />
<action android:id="@+id/action_show_b1" app:destination="@+id/dest_fragment_b1"/>
<action android:id="@+id/action_show_b2" app:destination="@+id/dest_fragment_b2"/>
</navigation>
With a MaterialButtonToggleGroup
in the parent FragmentB
, you can navigate using the <action>
tags in the above navigation graph:
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="@+id/toggleGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
app:checkedButton="@+id/button1"
app:singleSelection="true"
app:layout_constraintBottom_toTopOf="@+id/childNavHostFragment"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.25">
<com.google.android.material.button.MaterialButton
style="?attr/materialButtonOutlinedStyle"
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checkable="true"
android:text="Show B1"
/>
<com.google.android.material.button.MaterialButton
style="?attr/materialButtonOutlinedStyle"
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Show B2"
/>
</com.google.android.material.button.MaterialButtonToggleGroup>
FragmentB
code, note that you need to "find" the correct NavController
using the childNavHostFragment container
class FragmentB : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_b_layout, container, false)
}
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
val childNavController = childNavHostFragment?.findNavController()
button1.setOnClickListener {childNavController?.navigate(R.id.action_show_b1)}
button2.setOnClickListener {childNavController?.navigate(R.id.action_show_b2)}
}
}