web-dev-qa-db-fra.com

Composant d'architecture de navigation Android - Icônes du tiroir de navigation

J'utilise actuellement la variable Navigation du composant d'architecture Android, mais je rencontre un problème avec mon Navigation Drawer. Il affiche le menu des hamburgers à ma destination de départ, mais les autres Fragments affichent la flèche vers le haut. Je crois que j'ai configuré mon navigation_graph de manière incorrecte.

Ici vous pouvez voir mon tiroir de navigation, montrant 2 éléments, Accueil et Paramètres. Lorsque vous êtes dans l'un de ces fragments, vous devriez voir l'icône Hamburger.

 nav drawer

Cependant, lors de la navigation dans le fragment de paramètres, la flèche vers le haut est affichée.

 toolbar

navigation.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"
    app:startDestination="@id/nav_home">

    <!-- Start at HomeFragment -->
    <fragment
        Android:id="@+id/nav_home"
        Android:name=".HomeFragment"
        Android:label="@string/home">

        <!-- Navigate to the Search -->
        <action
            Android:id="@+id/action_nav_home_to_nav_search"
            app:destination="@id/nav_search" />
    </fragment>


    <fragment
        Android:id="@+id/nav_settings"
        Android:name=".SettingsFragment"
        Android:label="@string/settings">

        <!-- Navigate to the Search -->
        <action
            Android:id="@+id/action_nav_settings_to_nav_search"
            app:destination="@id/nav_search" />
    </fragment>



    <fragment
        Android:id="@+id/nav_search"
        Android:name=".SearchFragment"
        Android:label="@string/search" />

</navigation>

Je pense que HomeFragment et SettingsFragment devraient être liés d'une manière ou d'une autre, mais je ne sais pas comment définir cela.

main_drawer.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <group Android:checkableBehavior="single">
        <item
            Android:id="@id/nav_home"
            Android:icon="@drawable/ic_home_white_24dp"
            Android:title="@string/home" />

        <item
            Android:id="@id/nav_settings"
            Android:icon="@drawable/ic_settings_white_24dp"
            Android:title="@string/settings" />
    </group>
</menu>

Activité principale

Et puis dans MainActivity, je viens de le configurer comme ceci. J'ai appelé setupActionBarWithNavController, mais je dois également configurer le tiroir de navigation moi-même et gérer le onNavigationItemSelected.

private fun setupNavigation() {
    navController = findNavController(R.id.mainNavigationFragment)
    setupActionBarWithNavController(this, navController, drawer_layout)

    val toggle = ActionBarDrawerToggle(
                this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
        drawer_layout.addDrawerListener(toggle)
        toggle.syncState()

    nav_view.setNavigationItemSelectedListener(this)
}

override fun onNavigationItemSelected(item: MenuItem): Boolean {
    val current = navController.currentDestination.id
    if (item.itemId != current) {
        navController.navigate(item.itemId)
    }

    drawer_layout.closeDrawers()
    return true
}

build.gradle

// Navigation
implementation 'Android.Arch.navigation:navigation-fragment-ktx:1.0.0-alpha04'
implementation 'Android.Arch.navigation:navigation-ui-ktx:1.0.0-alpha04'

Merci.

11
Advice-Dog

Dans les alphas plus récents (j'ai 1.0.0-alpha07), ils ont ajouté la possibilité de définir topLevelDestinationIds lors de l'appel du constructeur AppBarConfiguration.

J'ai donc configuré mon NavController comme ceci

    val navController = findNavController(R.id.nav_Host_fragment)
    val config = AppBarConfiguration(
        setOf(
            R.id.fistTopFragment,
            R.id.secondTopFragment,
            ...
        ),
        dr.drawerLayout
    )
    tb.setupWithNavController(navController, config)

dr est MaterialDrawer et tb of course Toolbar.

Ensuite, il se comporte davantage comme Gmail, du moins pour la variable ActionBarDrawerToggle, la pile arrière est toujours conservée. Étant donné que je dois gérer moi-même la sélection d'éléments dans MaterialDrawer, je vais réduire les actions de pile arrière en utilisant des actions de navigation globales avec popTo inclusif au fragment racine du graphique de navigation et utiliser quelque chose comme un "écran de bienvenue" pour l'instant. 

Un autre moyen de contourner le problème pourrait être la gestion personnalisée de la variable onBackPressed. Vous devez d’abord supprimer app:defaultNavHost="true" de votre fragment d’hôte dans la structure d’activité. Quelque chose comme ça

override fun onBackPressed() {
    val navController = findNavController(R.id.nav_Host_fragment)
    if (navController.currentDestination == null
        || navController.currentDestination!!.id in setOf(
            R.id.fistTopFragment,
            R.id.secondTopFragment,
            ...
        )
    ) {
        super.onBackPressed()
    } else {
        navController.navigateUp()
    }
}

Désolé pour le code, j'apprends toujours Kotlin, donc il y a probablement beaucoup plus agréable de le faire.

3
Almighty

Je crains que ce soit un caractéristique de la composante de navigation .

La barre d’action affiche également le bouton Haut lorsque vous vous trouvez sur une destination non root et l’icône du tiroir lorsque vous vous trouvez sur la destination racine, s’animant automatiquement entre eux.

Si vous le souhaitez, vous pouvez utiliser setupWithNavController (NavigationView, NavController) et gérer la barre d’outils vous-même.

3
ferini

Si vous le souhaitez, vous pouvez utiliser NavController.OnNavigatedListener et utiliser le code ci-dessous pour définir le titre.

@Override
public void onNavigated(@NonNull NavController controller, @NonNull NavDestination destination) {
    mActivityBinding.toolbar.setTitle(destination.getLabel());
}

N'oubliez pas de définir l'étiquette dans votre graphique de navigation.

1
Roshni Kyada

Je pense que vos éléments de menu devraient être comme ceci:

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

    <item
            Android:id="@id/nav_home"
            Android:icon="@drawable/ic_home_white_24dp"
            Android:title="@string/home" />

        <item
            Android:id="@id/nav_settings"
            Android:icon="@drawable/ic_settings_white_24dp"
            Android:title="@string/settings" />

</menu>

J'espère que cela t'aides

Bon codage ... 

0
Abdul Aziz

J'ai fait un exemple simple pour ce problème. La solution est presque la même que la réponse d’Almight. https://github.com/isaul32/Android-sunflower

Créez d'abord un ensemble de destinations de premier niveau

val topLevelDestinations = setOf(R.id.garden_fragment,
        R.id.plant_list_fragment)
appBarConfiguration = AppBarConfiguration.Builder(topLevelDestinations)
        .setDrawerLayout(drawerLayout)
        .build()

puis remplacez la fonction onSupportNavigateUp comme ceci

override fun onSupportNavigateUp(): Boolean {
    return NavigationUI.navigateUp(navController, appBarConfiguration)
}
0
iSaul

La flèche de retour apparaissant sur les fragments d’onglet associés à BottomNavigationView est un comportement souhaité. Cependant, je ne l'ai pas vu utilisé "tel quel", même dans des applications célèbres (Instagram, Youtube qui ont des onglets inférieurs). Si vous naviguez par exemple vers différents onglets du bas dans l'application Youtube et que vous cliquez sur l'option de retour du périphérique, vous remarquerez qu'elle passe au fragment d'onglet précédent et ne quitte pas l'application. Ainsi, les fragments d'onglet bottomnavigationview ne sont pas des destinations racine ici.

Vous souhaitez attirer l'attention sur d'autres problèmes importants que vous pourriez rencontrer à l'avenir:

Toutefois, vous pouvez utiliser plusieurs points d'ancrage pour personnaliser le comportement:

  1. onBackPressed - pour fermer la disposition des tiroirs si elle est ouverte

    override fun onBackPressed() {
        if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
          drawerLayout.closeDrawer(GravityCompat.START)
        } else {
          super.onBackPressed()
        }
     }
    
  2. Ajoutez navController.addOnNavigatedListener(..) et à l’intérieur du programme d’écoute, personnalisez l’icône HomeAsUpIndicator

  3. Remplacez onOptionsItemSelected pour personnaliser le menu avec l'action id Android.R.id.home

  4. Définir un navigateur de fragments personnalisé pour personnaliser le traitement de vos fragments (remplacer ou afficher/masquer) 

    navHostFragment = supportFragmentManager
            .findFragmentById(R.id.my_nav_Host_fragment) as NavHostFragment? ?: return
    val customNavigator = CustomFragmentNavigator(navHostFragment.requireContext(),
            navHostFragment.childFragmentManager, navHostFragment.id)
    navHostFragment.navController.navigatorProvider.addNavigator(customNavigator)
    
    val inflater = navHostFragment.navController.navInflater
    val graph = inflater.inflate(R.navigation.main_nav_graph)
    navHostFragment.navController.graph = graph
    

Rappelez-vous que le composant de navigation Arch est toujours en alpha, utilisez-le donc judicieusement.

0
random

Je suis tout à fait d'accord avec le sentiment mais c'est une partie de la bibliothèque

setupActionBarWithNavController

Configure le ActionBar renvoyé par AppCompatActivity.getSupportActionBar () pour une utilisation avec NavController.

En appelant cette méthode, le titre dans la barre d'action sera automatiquement mis à jour lorsque la destination changera (en supposant qu'il existe une étiquette valide).

La destination de départ de votre graphique de navigation est considérée comme la seule destination de niveau supérieur. Sur la destination de départ de votre graphique de navigation, la barre d’action affichera l’icône du tiroir si DrawerLayout est non null. Sur toutes les autres destinations, la barre d’action affichera le bouton Haut. Appelez browseUp (NavController, DrawerLayout) pour gérer le bouton Haut.

pour moi, c’est cassé et pas le résultat souhaité, donc ce que je fais est toujours de l’utiliser avec la vue de navigation en utilisant 

    navController = Navigation.findNavController(this, R.id.nav_Host);
    NavigationUI.setupWithNavController(navigationView,navController);

puis avoir un auditeur pour mettre à jour le titre et tout ce que je veux changé comme celui-ci 

   navController.addOnNavigatedListener((controller, destination) -> {
        setToolbarColour(R.color.primary);
        switch (destination.getId()){
            case R.id.dashBoard :
                setToolbarColour(Android.R.color.transparent);
                break;
            case R.id.requests :
                toolbar.setTitle(getString(R.string.request));
                break;

        }
    });

Je crée ensuite un nouveau graphe de navigation pour chacun de ces fragments, ce qui n'est pas génial, mais j'obtiens le résultat souhaité.

0
martinseal1987