Créer une BottomBar/TabBar personnalisée en se basant sur React-Native-Navigation

Cette article prend comme base l’application mise en place dans mon article Mettre en place d’une BottomBar/TabBar avec React-Native-Navigation et React-Native-Vector-Icons. Si vous n’êtes pas à l’aise avec la mise en place des ces 2 bibliothèques, n’hésitez pas à y jeter un coup d’oeil (ou simplement pour étudier la structure de l’application, et les fichiers utilisés dans cet article)

La majorité des projets que je développe utilise la BottomBar/TabBar pour leur menu (dans la suite de l’article, j’utiliserai le terme de TabBar uniquement).

Les porteurs de projet sont souvent demandeurs de rester dans les schémas établis par les éditeurs, mais certains préféreraient une TabBar complètement personnalisée, pour marquer une différence.

Alors j’ai voulu faire un test pour utiliser le navigation native de React-Native-Navigation, tout en ajoutant une TabBar personnalisé en lieu et place de la TabBar native.

Création de la TabBar personnalisée

Nous allons créer un nouveau fichier dans notre dossier component, que nous allons tout simplement nommé tabbar.js. Comme pour les autres écrans nous allons le déclarer dans constants.js et dans screens.js.

et

Le but va être d’ouvrir cet écran en tant qu’overlay avec React-Native-Navigation. Ainsi, il va s’afficher par dessus, notre application. Dans cet écran, nous allons donc créer une vue qui aura la même taille que la TabBar, pour qu’elle vienne s’afficher par dessus, et nous spécifierons dans les options de l’overlay, que cet écran ne doit pas intercepter les actions faites en dehors de cette vue (avec l’option interceptTouchOutside à false). Egalement, nous devrons préciser dans l’objet layout que le fond doit être transparent pour que sur iOS, il ne soit pas blanc, ce qui masquerait le contenu de l’application.

Commençons par créer cet écran, en affichant une vue de 60 de haut, prenant toute la largeur, et alignée vers le bas, pour comprendre le principe de cet overlay.

Voici le code de notre écran tabbar.js

Nous allons afficher cet écran en overlay. Pour cela nous allons appeler la méthode showOverlay de React-Native-Navigation, juste après avoir défini notre TabBar en tant que root, dans notre fichier index.js.

Dans mon fichier demos.js, je rajoute un bouton pour afficher une alerte qui dit “coucou”, afin de montrer que l’affichage de cet overlay n’empêche pas les actions dans l’application.

On peut voir que sur iOS, la TabBar n’est que partiellement recouverte, alors que sur Android, elle l’est complètement. Pour être sûr d’avoir une TabBar personnalisé de la même dimensions que la TabBar native, nous allons utiliser les constantes de React-Native-Navigation qui nous donne les hauteurs de la NavigationBar, de la StatusBar et de la TabBar.

Dans la méthode componentDidMount() appelée au chargement de l’écran tabbar.js, nous allons donc appeler la méthode constants(), pour enregistrer la hauteur de la TabBar native, et appliqué cette hauteur à notre TabBar personnalisée. En cas d’erreur de la méthode constants(), je ne fais rien de plus. La hauteur par défaut étant 0, cela signifie que nous n’auront pas de vue au dessus de notre TabBar native, et donc l’application fonctionnera toujours.

Le code de notre écran tabbar.js devient :

Il faut maintenant gérer le cas de l’orientation. En effet, vous verrez que si vous mettez vos simulateurs en paysage, la TabBar n’est pas redessinée et ne recouvre que la moitié de la TabBar native en largeur. Nous allons donc faire appel à la méthode addEventListener de la bibliothèque Dimensions, qui sera déclenchée à chaque changement de dimensions de l’écran (donc quand il est tourné). À chaque déclenchement, on appellera à nous la méthode getBottomTabsHeight(), qui mettra à jour la hauteur et donc l’écran.

Les modifications à apporter à tabbar.js sont très simples.

Il nous faut maintenant, ajouter les 2 boutons de notre TabBar pour afficher les écrans correspondant. Pour cela nous appellerons la méthode mergeOptions de la bibliothèque React-Native-Navigation. Nous devons donner un ID unique à notre bottomTabs, puis indiquer à React-Native-Navigation l’index de l’écran à afficher (les index étant 0 pour l’écran demos.js, 1 pour l’écran articles.js et 2 pour l’écran about.js).

L’idée va être d’afficher seulement les icônes, sauf pour l’élément sélectionné qui aura son titre également. Pour cela, nous allons créer un tableau contenant les 3 éléments de la TabBar, avec pour chacun l’icône et le titre associé. Une boucle nous permettra de créer la vue de chaque élément, et d’afficher ou non le titre de l’élément si celui-ci est sélectionné.

Commençons par donner un ID unique à notre bottomTabs. Je vais déclarer cet ID dans le fichier constants.js, et y faire appel dans mon fichier index.js pour l’affecter à la bottomTabs, puis dans mon fichier tabbar.js pour changer les écrans.

Commençons par le changement dans index.js

Puis le changement de tabbar.js

On peut maintenant voir que la TabBar fonctionne bien.

Le but d’avoir une TabBar personnalisée est d’avoir un comportement original. Or ici, nous avons simplement reproduit un comportement de base. Pour produire un résultat original, je me suis inspiré du widget Flutter google_nav_bar, designé par Aurelien Salomon et développé par sooxt98, dont la version 2 a été publiée cette semaine.

Dans un premier temps nous allons :

  • passer la couleur de fond de notre TabBar en blanc,
  • associer une couleur à chaque élément,
  • associé cette couleur en tant que couleur de fond de chaque élément, s’ils sont sélectionnés,
  • et enfin afficher le titre de l’élément à droite de l’icône et non en dessous.

Nous allons légèrement modifier les boutons pour qu’il puisse prendre la forme souhaitée quand ils sont sélectionnés.

Voici les changements à effectuer dans tabbar.js

Nous obtenons déjà un résultat différent, mais il manque de fluidité. Nous allons donc ajouter des animations pour le rendre plus fluide. Le but est d’agrandir la zone colorée, et ensuite d’y afficher le texte.

Nous n’allons pas aller au bout de la finesse du package google_nav_bar, mais nous allons quand même essayer d’arriver à un résultat appréciable.

Nous allons donc utiliser la bibliothèque Animated. Nous allons ajouter la variable animatedSelectedIndex qui nous permettra de déclencher les animations. Cette variable sera une copie du selectedIndex, et aura pour effet de changer la taille des éléments de la TabBar, la couleur de fond de l’élément, ainsi que l’opacité du texte. Nous allons donc également créer 3 méthodes pour gérer ces 3 valeurs. Nous changerons également la couleur de l’icône pour qu’elle soit blanche quand l’élément est sélectionné, et grise sinon. Enfin nous changerons le code de la méthode showScreenWithIndex() pour changer la valeur de notre variable animatedSelectedIndex, et déclencher les animations.

Voilà donc le code de tabbar.js pour prendre en compte ces changements.

Et voilà le résultat !

Show Runner de projets mobiles. Développeur React Native et passionné par les challenges du monde mobile.

Love podcasts or audiobooks? Learn on the go with our new app.