web-dev-qa-db-fra.com

Existe-t-il un moyen de garder le fragment en vie lorsque vous utilisez BottomNavigationView avec le nouveau NavController?

J'essaie d'utiliser le nouveau composant de navigation. J'utilise BottomNavigationView avec le navController: NavigationUI.setupWithNavController (bottomNavigation, navController)

Mais lorsque je change de fragment, il est à chaque fois détruit/créé, même s’il était utilisé auparavant.

Existe-t-il un moyen de garder en vie nos principaux fragments liés à notre BottomNavigationView?

23
IdAndro

Essaye ça.

Navigateur

Créer un navigateur personnalisé.

@Navigator.Name("custom_fragment")  // Use as custom tag at navigation.xml
class CustomNavigator(
    private val context: Context,
    private val manager: FragmentManager,
    private val containerId: Int
) : FragmentNavigator(context, manager, containerId) {

    override fun navigate(destination: Destination, args: Bundle?, navOptions: NavOptions?) {
        val tag = destination.id.toString()
        val transaction = manager.beginTransaction()

        val currentFragment = manager.primaryNavigationFragment
        if (currentFragment != null) {
            transaction.detach(currentFragment)
        }

        var fragment = manager.findFragmentByTag(tag)
        if (fragment == null) {
            fragment = destination.createFragment(args)
            transaction.add(containerId, fragment, tag)
        } else {
            transaction.attach(fragment)
        }

        transaction.setPrimaryNavigationFragment(fragment)
        transaction.setReorderingAllowed(true)
        transaction.commit()

        dispatchOnNavigatorNavigated(destination.id, BACK_STACK_DESTINATION_ADDED)
    }
}

NavHostFragment

Créez un NavHostFragment personnalisé.

class CustomNavHostFragment: NavHostFragment() {
    override fun createFragmentNavigator(): Navigator<out FragmentNavigator.Destination> {
        return CustomNavigator(requireContext(), childFragmentManager, id)
    }
}

navigation.xml

Utilisez une balise personnalisée au lieu d'une balise fragment. 

<navigation xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto" Android:id="@+id/navigation"
    app:startDestination="@id/navigation_first">

    <custom_fragment
        Android:id="@+id/navigation_first"
        Android:name="com.example.sample.FirstFragment"
        Android:label="FirstFragment" />
    <custom_fragment
        Android:id="@+id/navigation_second"
        Android:name="com.example.sample.SecondFragment"
        Android:label="SecondFragment" />
</navigation>

mise en page de l'activité

Utilisez CustomNavHostFragment au lieu de NavHostFragment.

<androidx.constraintlayout.widget.ConstraintLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:id="@+id/container"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <fragment
        Android:id="@+id/nav_Host_fragment"
        Android:name="com.example.sample.CustomNavHostFragment"
        Android:layout_width="0dp"
        Android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/navigation" />

    <com.google.Android.material.bottomnavigation.BottomNavigationView
        Android:id="@+id/bottom_navigation"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/navigation" />

</androidx.constraintlayout.widget.ConstraintLayout>

Mettre à jour

J'ai créé un exemple de projet. lien

Je ne crée pas NavHostFragment personnalisé. J'utilise navController.navigatorProvider += navigator.

25
STAR_ZERO

Non disponible à partir de maintenant.

En guise de solution de contournement, vous pouvez stocker toutes vos données extraites dans le modèle d'affichage et les disposer facilement lorsque vous recréez le fragment. Assurez-vous d'obtenir la vue en utilisant le contexte des activités.

Vous pouvez utiliser LiveData pour rendre vos données observables sensibles au cycle de vie des données.

0
Samuel Robert