Loupe

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 !

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus