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.
Cependant, lors de la navigation dans le fragment de paramètres, la flèche vers le haut est affichée.
<?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.
<?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>
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.
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)
Où 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.
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.
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.
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 ...
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)
}
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:
Il ne permet pas la réutilisation de fragments en combinaison avec BottomNavigationView
https://issuetracker.google.com/issues/110373186
Si vous avez plusieurs activités, le bouton Haut ne permet pas d'accéder à l'activité précédente https://issuetracker.google.com/issues/79993862
Toutefois, vous pouvez utiliser plusieurs points d'ancrage pour personnaliser le comportement:
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()
}
}
Ajoutez navController.addOnNavigatedListener(..)
et à l’intérieur du programme d’écoute, personnalisez l’icône HomeAsUpIndicator
Remplacez onOptionsItemSelected
pour personnaliser le menu avec l'action id Android.R.id.home
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.
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é.