web-dev-qa-db-fra.com

Utilisation simultanée du tiroir de navigation et de la navigation inférieure - Composant d'architecture de navigation

J'ai un écran comme ci-dessous qui contient un tiroir de navigation et une navigation en bas sur le même écran:

app screen

J'utilise le composant d'architecture de navigation Jetpack.

Problème actuel et ce que j'ai essayé?

Un clic sur les 2e et 3e éléments de navigation du bas affiche la flèche de retour sur la barre d'outils.

Essayé: définir des fragments associés aux 2e et 3e nav du bas vers des destinations de premier niveau

appBarConfig = AppBarConfiguration(setOf(R.layout.fragment_star, R.layout.fragment_stats, R.layout.fragment_user))

au lieu de

appBarConfig = AppBarConfiguration(navController.graph, drawerLayout)

N'a pas fonctionné.

Toute aide très appréciée!


Mon code ressemble à ci-dessous.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto">

    <androidx.drawerlayout.widget.DrawerLayout
        Android:id="@+id/drawerLayout"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:fitsSystemWindows="true">


        <LinearLayout
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:orientation="vertical">

            <androidx.appcompat.widget.Toolbar
                Android:id="@+id/toolbar"
                Android:layout_width="match_parent"
                Android:layout_height="?attr/actionBarSize"
                Android:background="?attr/colorPrimary"
                app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

            <fragment
                Android:id="@+id/navHostFragment"
                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" />

            <com.google.Android.material.bottomnavigation.BottomNavigationView
                Android:id="@+id/bottomNav"
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:layout_gravity="bottom"
                Android:background="?android:attr/windowBackground"
                app:menu="@menu/menu_bottom" />

        </LinearLayout>

        <!-- gives navDrawer material look-->
        <com.google.Android.material.navigation.NavigationView
            Android:id="@+id/navView"
            Android:layout_width="wrap_content"
            Android:layout_height="match_parent"
            Android:layout_gravity="start"
            app:menu="@menu/nav_drawer_menu"
            app:headerLayout="@layout/nav_header"
            Android:fitsSystemWindows="true"
            />
    </androidx.drawerlayout.widget.DrawerLayout>
</layout>

menu_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">

    <item
        Android:id="@+id/starFragment"
        Android:icon="@drawable/ic_star_green_48dp"
        Android:title="@string/bottom_nav_title_star"/>

    <item
        Android:id="@+id/statsFragment"
        Android:icon="@drawable/ic_stats_green_48dp"
        Android:title="@string/bottom_nav_title_stats"/>

    <item
        Android:id="@+id/userFragment"
        Android:icon="@drawable/ic_user_green_48dp"
        Android:title="@string/bottom_nav_title_user"/>

</menu>

nav_graph.xml

<?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"
            xmlns:tools="http://schemas.Android.com/tools" Android:id="@+id/nav_graph_main"
            app:startDestination="@id/starFragment">

    <fragment
        Android:id="@+id/starFragment"
        Android:name="com.example.app.ui.StarrFragment"
        Android:label="Star"
        tools:layout="@layout/fragment_star">
    </fragment>
    <fragment
        Android:id="@+id/statsFragment"
        Android:name="com.example.app.StatsFragment"
        Android:label="fragment_stats"
        tools:layout="@layout/fragment_stats" />
    <fragment
        Android:id="@+id/userFragment"
        Android:name="com.example.app.UserFragment"
        Android:label="fragment_user"
        tools:layout="@layout/fragment_user" />
</navigation>

ActivityMain.kt

class MainActivity : AppCompatActivity() {

    private lateinit var drawerLayout: DrawerLayout
    private lateinit var appBarConfig: AppBarConfiguration
    private lateinit var navController: NavController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
        setSupportActionBar(toolbar)

        drawerLayout = binding.drawerLayout
        navController = this.findNavController(R.id.navHostFragment)

        binding.bottomNav.setupWithNavController(navController)

        NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout)
        appBarConfig = AppBarConfiguration(navController.graph, drawerLayout)


        // lock drawer when not in start destination
        navController.addOnDestinationChangedListener { nc, nd, _ ->

            if(nd.id == nc.graph.startDestination){
                drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
            }
            else{
                drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
            }
        }

         NavigationUI.setupWithNavController(binding.navView, navController)
    }

    override fun onSupportNavigateUp(): Boolean {

        // replace navigation up button with nav drawer button when on start destination
        return NavigationUI.navigateUp(navController, appBarConfig)

    }
}
9
user158

Pas besoin d'écrire un code séparé pour remplacer le bouton de retour par l'icône du tiroir.

Dans AppBarConfiguration, passez les identifiants de fragment (de nav_graph) que vous utilisez pour naviguer à la fois dans le tiroir de navigation et de navigation inférieur. (P.S( les fragments et son icône associée doivent avoir les mêmes identifiants )

Pour votre cas, la AppBarConfiguration devrait ressembler à ceci:

appBarConfig = AppBarConfiguration.Builder(R.id.starFragment, R.id.statsFragment, R.id.userFragment)
                .setDrawerLayout(drawerLayout)
                .build()

Configurez la barre d'actions:

setSupportActionBar(toolbar)
setupActionBarWithNavController(navController, appBarConfig)

Maintenant, configurez navcontroller pour la navigation inférieure et la vue de navigation:

navView.setupWithNavController(navController)
bottomNav.setupWithNavController(navController)

la fonction onSupportNavigateUp doit être:

override fun onSupportNavigateUp(): Boolean {
        return navController.navigateUp(appBarConfig)
    }

La pression sur le bouton Retour doit être manipulée si le tiroir est ouvert:

override fun onBackPressed() {
        if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
            drawerLayout.closeDrawer(GravityCompat.START)
        } else {
            super.onBackPressed()
        }
    }

Bonus

Par défaut, lorsque vous cliquez sur l'icône de navigation inférieure dans l'ordre icon_1 puis icon_2 puis icon_3 et à partir de là, vous appuyez sur le bouton de retour, il reviendra à l'icône d'accueil qui est icon_1

Si vous souhaitez revenir en arrière dans l'ordre inverse dans lequel vous avez cliqué sur les icônes (à la manière de la pile arrière), ajoutez ensuite Android: menuCategory = "secondaire" à l'élément du menu. Votre menu ressemblera donc à:

<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item
        Android:id="@+id/starFragment"
        Android:icon="@drawable/ic_star_green_48dp"
        Android:title="@string/bottom_nav_title_star"
        Android:menuCategory="secondary"/>
    <item
        Android:id="@+id/statsFragment"
        Android:icon="@drawable/ic_stats_green_48dp"
        Android:title="@string/bottom_nav_title_stats"
        Android:menuCategory="secondary"/>
    <item
        Android:id="@+id/userFragment"
        Android:icon="@drawable/ic_user_green_48dp"
        Android:title="@string/bottom_nav_title_user"
        Android:menuCategory="secondary"/>
</menu>

J'espère que l'icône du bouton de retour sera résolue maintenant :)

7
Atr07

Ce projet utilise DrawerLayout et simule BottomNavigationView à l'aide de RadioButtons, c'est ainsi que j'ai trouvé pour résoudre le problème


Dans le projet de navigation Google Codelab, ils font ce que mentionne Adithya T Raj, mais cela ne sert qu'à afficher DrawerLayout sur paysage et BottomNavigationView sur Portrait. Le lien du projet :

J'essaie de les forcer à me montrer les deux sur cette branche mais seul le DrawerLayout est affiché

1
evaldez

Tout d'abord, ce n'est pas une bonne approche de conception. Si vous voulez quelque chose comme ça, vous devez utiliser la barre d'application inférieure (pas la vue de navigation inférieure avec le tiroir de navigation)

Voici le guide pour vous: Lien vers l'article

Vous pouvez facilement adapter votre application avec cela.

0
Halil ÖZCAN