Android : toujours afficher les textes sur une BottomNavigationView
La BottomNavigationView permet de créer une barre de navigation à base d'onglet en bas de l'écran. Ce mécanisme de navigation permet d'accéder rapidement aux différentes sections de votre application sans avoir à atteindre le haut de l'écran. Il est donc tout particulièrement adapté à une application ayant peu de "sections". Sur Android (à la différence d'iOS), les textes associés aux icônes disparaissent dès qu'il y a plus de 3 éléments (c'est en dur dans le code du SDK...). Je trouve cela dommage car la signification d'une icône n'est pas toujours évidente et vos utilisateurs peuvent se sentir perdus. Dans cet article, nous verrons comment laisser les textes dans toutes les situations.
Comportement par défaut
Par défaut, le texte n'est affiché que sur l'élément actuellement sélectionné.
La solution technique
La solution consiste à parcourir l'arbre visuel de la BottomNavigationView pour aller chercher les enfants de type BottomNavigationItemView et renseigner leur propriété ShiftingMode à false. Ensuite il faut déclencher une mise à jour de l'interface en sélectionnant l'élément. On prendra soin de s'assurer de restaurer l'élément sélectionné au début du traitement.
Xamarin Platform
Sur Xamarin Platform, on utilise les API natives et le traitement est assez simple à écrire dans une méthode utilitaire. En bonus, on en profite pour réduire un peu la taille des textes que l'on peut trouver un peu gros. La BottomNavigationView peut être trouvée de manière classique via un FindViewById puisqu'on le place directement dans notre layout.
var bottomNavigationView = _bottomNavigationView; // récupération de l'élément sélectionné // au début du traitement int selectedAtStart = 0; for (int i = 0; i < bottomNavigationView.Menu.Size(); i++) { if (bottomNavigationView.Menu.GetItem(i).IsChecked) { selectedAtStart = i; break; } } // recherche de l'élément BottomNavigationMenuView for (int j = 0; j < bottomNavigationView.ChildCount; ++j) { var menuView = bottomNavigationView.GetChildAt(j) as BottomNavigationMenuView; if (menuView != null) { // parcourt des BottomNavigationItemView for (int i = menuView.ChildCount - 1; i >= 0; i--) { var item = (BottomNavigationItemView)menuView.GetChildAt(i); // SetShiftingMode = false pour désactiver le "masquage" des // textes. itemView.SetShiftingMode(false); // bonus pour changer la taille des labels var itemTitle =(BaselineLayout) item.GetChildAt(1); TextView t = (TextView)(itemTitle).GetChildAt(0); t.SetTextSize(ComplexUnitType.Px, t.TextSize * 0.9f); t = (TextView)(itemTitle).GetChildAt(1); t.SetTextSize(ComplexUnitType.Px, t.TextSize * 0.9f); } // unselect every items for (int i = 0; i < bottomNavigationView.Menu.Size(); i++) { bottomNavigationView.Menu.GetItem(i).SetChecked(false); } // select the one selected at start var itemViewToSelect = (BottomNavigationItemView)menuView.GetChildAt(selectedAtStart); itemViewToSelect.SetChecked(true); itemViewToSelect.PerformClick(); break; } }
Et nous avons alors le comportement souhaité !
Xamarin Forms
Ici, il faudra créer un renderer sur notre TabbedPage et faire la personnalisation à ce moment là. Cela tombe bien car Thomas a déjà bloggé sur le Renderer à mettre en place !
À partir celui-ci, on va aller chercher la BottomNavigationView à chaque changement d'élément et appliquer le traitement ci-dessus. Ici aussi, on devra parcourir l'arbre visuel pour la trouver. Voici le code à appliquer :
for (int i = 0; i <= ViewGroup.ChildCount - 1; i++) { var childView = ViewGroup.GetChildAt(i); if (childView is ViewGroup viewGroup) { for (int j = 0; j <= viewGroup.ChildCount - 1; j++) { var childRelativeLayoutView = viewGroup.GetChildAt(j); if (childRelativeLayoutView is BottomNavigationView btv) { _bottomNavigationView = btv; break; } } } if (_bottomNavigationView != null) { break; } }
Et nous avons alors le comportement souhaité !
Happy coding !
Commentaires