Sobes.tech
Middle

Hoe zou je navigatie met knoppen implementeren zodat deze de stack behoudt?

sobes.tech AI

Antwoord van AI

Ik zou de Navigation Architecture Component gebruiken.

  1. NavGraph maken: Ik zou Destinations (fragmenten of Activity's) en Actions (overgangen tussen hen) definiëren in een XML-resource.

    <?xml version="1.0" encoding="utf-8"?>
    <navigation xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/nav_graph"
        app:startDestination="@id/fragmentA"> // Startpunt
    
        <fragment
            android:id="@+id/fragmentA"
            android:name="com.example.FragmentA"
            android:label="FragmentA" >
            <action
                android:id="@+id/action_fragmentA_to_fragmentB"
                app:destination="@id/fragmentB" />
        </fragment>
        <fragment
            android:id="@+id/fragmentB"
            android:name="com.example.FragmentB"
            android:label="FragmentB" >
            <action
                android:id="@+id/action_fragmentB_to_fragmentC"
                app:destination="@id/fragmentC" />
        </fragment>
         <fragment
            android:id="@+id/fragmentC"
            android:name="com.example.FragmentC"
            android:label="FragmentC" />
    </navigation>
    
  2. NavHost plaatsen: Ik zou een NavHost (bijvoorbeeld NavHostFragment) toevoegen aan het layout van de Activity, gekoppeld aan de NavGraph.

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph" /> // Koppeling met NavGraph
    
        <!-- Navigatieknoppen kunnen hier -->
    </LinearLayout>
    
  3. Navigatieknoppen toevoegen: Ik zou BottomNavigationView of aparte knoppen gebruiken. Voor BottomNavigationView zou ik deze koppelen aan de NavController.

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph" />
    
        <Button
            android:id="@+id/button_go_to_b"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Ga naar B" />
    
        <Button
            android:id="@+id/button_go_to_c"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Ga naar C" />
    </LinearLayout>
    
  4. Button-klikafhandeling in code: Ik zou een instantie van NavController krijgen en navigate() aanroepen bij het klikken. NavController beheert automatisch de back stack, waarbij de vorige Destination behouden blijft.

    // In Activity of Fragment
    import androidx.navigation.findNavController
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
    
        val navController = findNavController(R.id.nav_host_fragment) // Verkrijg NavController
    
        view.findViewById<Button>(R.id.button_go_to_b).setOnClickListener {
            navController.navigate(R.id.action_fragmentA_to_fragmentB) // Overgang via Action
        }
    
        view.findViewById<Button>(R.id.button_go_to_c).setOnClickListener {
            // Directe overgang naar Destination, kan `action_fragmentA_to_fragmentC` gebruiken als die bestaat
             navController.navigate(R.id.fragmentC)
        }
    }
    

Voor complexere navigatie met meerdere tabbladen (BottomNavigationView, DrawerLayout) zou ik setupWithNavController() gebruiken.

// In Activity met BottomNavigationView
import androidx.navigation.ui.setupWithNavController
import com.google.android.material.bottomnavigation.BottomNavigationView

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val navController = findNavController(R.id.nav_host_fragment)
    val bottomNavView = findViewById<BottomNavigationView>(R.id.bottom_nav_view)
    bottomNavView.setupWithNavController(navController) // Koppeling van BottomNavigationView met NavController
}

Navigation Component beheert standaard de back stack. Het indrukken van de "Terug" knop brengt de gebruiker terug naar de vorige destination in de back stack. Om het gedrag van de back stack te beheren bij navigate(), kan je NavOptions met popUpTo gebruiken.