TabBar animé de Coinbase dans React Native


Présentation de l’expérience utilisateur «TabBar»

Vous avez probablement utilisé cette interaction d’innombrables fois dans votre vie quotidienne et vous n’avez pas passé beaucoup de temps à y penser. Vous le voyez sur des éléments tels que Instagram, Twitter, Apple Music ET, plus récemment, sur l’écran des prix de Coinbase.

Il s’agit d’un élément d’onglet simple, avec un en-tête déroulant et une barre d’onglets qui s’épinglent en haut de l’écran. Il vous permet de faire défiler les différents TabViews et traite intelligemment la position de défilement globale (c’est-à-dire que si vous faites défiler l’en-tête sur un TabView, le changement d’onglet maintient l’en-tête global dans la même position, quel que soit le défilement de l’onglet).

Cependant, malgré le fait que cette expérience UX soit devenue universelle, dans les coulisses, elle nécessite encore une grande quantité de gestes complexes et de gestion des états pour que cela se sente et fonctionne «parfaitement» pour l’utilisateur final.

TabBar animé de Coinbase dans React Native

ainsi que le code nécessaire pour y arriver.

Glossaire des termes UX

Nous avons également extrait un exemple de projet compagnon simple – que vous pouvez utiliser pour suivre ou aider à créer votre propre version de travail de cette expérience.

  • Entête Il s’agit du verrouillage typographique le plus élevé sur l’écran
  • Barre d’onglets Ceci est une liste de boutons d’onglet. Il met en évidence l’onglet actif et vous permet de naviguer entre chaque TabView avec un robinet ou un balayage
  • /li>/li>

  • Écran- Le composant conteneur de niveau supérieur (composant React de niveau racine)
  • Interpolation- Mappe les plages d’entrée sur les plages de sortie, généralement à l’aide d’une interpolation linéaire, mais prend également en charge les fonctions d’accélération
  • FPS- Images par seconde
  • Trafic du pont – Messages envoyés via le pont de React Native entre son javascript et sa couche native
  • TabView actif- Le TabView actuellement visible
  • Onglet inactif – TabViews qui sont hors écran (actuellement non visibles)
  • Guide des interactions

    Il existe une poignée d’interactions clés qui permettent de donner à TabView une apparence et une sensation organiques. Un grand nombre de ces comportements ont été identifiés grâce à l’étude d’implémentations externes telles que Twitter et Instagram, ainsi que d’applications et de spécifications spécifiques à des plates-formes telles que HIG d’Apple et Material Design de Google.

    Voici une liste d’interactions clés (que vous trouverez toutes dans notre exemple de projet sur github). Étudiez le gif ci-dessus pour voir si vous pouvez choisir chacun de ces comportements subtils.

  • La NavBar devrait s’effacer avec une animation basée sur la minuterie lorsque le défilement atteint une certaine position. De nombreuses personnes font l’erreur d’interpoler l’opacité du titre NavBar en fonction de la position de défilement de la page. Bien que cela fonctionne très bien lorsque vous faites défiler lentement, si vous faites défiler plus rapidement (standard dans l’utilisation quotidienne des applications), vous remarquerez que le titre de la NavBar entrera souvent trop brusquement. Nous avons d’abord remarqué ce comportement lors de l’analyse de l’interface utilisateur d’Apple Note, mais vous verrez dans toutes les applications natives d’Apple (Apple Music, Mail, etc.) qu’elles implémentent ce même point de déclenchement de fondu.Le point de déclenchement idéal pour cette animation est juste car le titre de l’en-tête est obstrué par la NavBar
  • Cette transformation donne l’apparence visuelle du défilement de l’en-tête avec TabBar et TabViews vers le haut et hors de la page, sans réellement faire défiler la page (plus d’informations sur la gestion de la position de défilement et la complexité qui en découle dans les détails de mise en œuvre ci-dessous)

    pour donner l’effet que les onglets sont épinglés sous la NavBar

    /li>

  • TabView doit défiler vers le haut et épingler directement sous la TabBar, garantissant que chaque fois que vous glissez ou naviguez entre les TabViews, la position de l’en-tête est toujours correctement maintenue.Comme TabBar, Tabview doit apparaître visuellement épinglé sous TabBar. Une fois épinglé, le contenu TabView devrait apparaître pour défiler sous la TabBar épinglée
  • Mise en œuvre

    visant à maintenir les interactions clés telles que la navigation, les gestes, etc. à 60 ips. Pour ce faire dans React Native, il est impératif à la fois de limiter le trafic des ponts (en réduisant les animations pilotées par JS) et de réduire les cycles de rendu (mettre à jour au minimum l’API d’état / de contexte).

    en ajoutant l’extrait ci-dessous à TabView onScroll un événement.

    com/media//hrefRemarque : nous mettons à jour l’événement scrollY ici en fonction de l’activation ou non d’un onglet donné. Cela garantit qu’il n’y a jamais qu’un seul TabView mettant à jour les positions de défilement à un moment donné.

  • Le titre de la NavBar doit s’effacer avec une animation basée sur une minuterie lorsque le défilement atteint une certaine position.
  • Lorsque cette valeur change Étant donné que notre barre de navigation est fixée en haut de l’écran

    com/media//href2. L’en-tête doit glisser vers le haut et hors de l’écran (sous la NavBar) lors du défilement.

    Value mise à jour à 0.3 et exécutions l’interpolation ci-dessous, la sortie interpolée serait 30.

    com/media//hrefDans cet esprit, considérons notre interpolation d’en-tête.

    com/media//hrefIci

    Cependant, il y a un peu de nuance ici en raison de la façon dont iOS traite 3 scénarios: tirer pour actualiser, bande élastique et défilement excessif.

    Cela permet à notre spinner «tirer pour actualiser» de se dérouler correctement sous notre en-tête (visuellement en haut de TabView).

    Nous pouvons nous en sortir sur Android, car il n’y a pas de défilement excessif.

    com/media//hrefEn revenant à notre interpolation d’en-tête, le inputRange utilisé doit être différent pour iOS (pour tenir compte du contentOffset). Spécifiquement:

    com/media//hrefLa dernière chose à noter ici est que nous interpolons ces valeurs d’entrée (ScrollOffset à ScrollOffset + Header) à une plage de sortie de (0 à une hauteur d’en-tête négative)

    Le résultat est que lorsque vous faites défiler TabView, l’en-tête sera transformé vers le haut et hors de l’écran jusqu’à ce qu’il soit complètement masqué (en-tête négatif), et pas plus.

    com/media//href3. Le TabBar doit glisser vers le haut, puis épingler sur le bord inférieur de la NavBar.

    haut: 0}

    puis c’est la position de rendu naturelle (contrairement à ce que nous avons fait avec notre composant Header) C’est pourquoi notre plage de sortie dans l’invocation ci-dessous définit une transformation initiale de la hauteur de l’en-tête et la convertit en sa position épinglée finale épinglée de 0.

    com/media//href4. Une fois que la TabBar est épinglée, une bordure inférieure doit être estompée pour ajouter de la profondeur aux TabViews glissant en dessous.

    Cela garantit que la bordure ne commence pas à s’effacer tant que l’en-tête n’a pas été défilé hors de la vue, et qu’elle est complètement estompée au moment où les enfants TabView défilent en dessous.

    Nous interpolons ensuite la valeur en une outputRange de 0 à 1, qui est la plage de valeurs de la propriété opacity dans React Native.

    com/media//href5. TabView doit glisser vers le haut et épingler directement sous la TabBar, garantissant que chaque fois que vous glissez ou naviguez entre les TabViews, la hauteur de l’en-tête est toujours correctement maintenue

    C’est sans doute la pièce la plus difficile de toute cette architecture. S’appuyer sur une seule valeur ScrollY simplifie grandement les interpolations ci-dessus, mais cela devient problématique dès que vous commencez à prendre en compte les TabViews inactives. Si vous ne faites rien pour synchroniser de manière proactive les vues de défilement inactives, la navigation entre les TabViews affichera des positions de défilement à des emplacements incorrects (car les TabViews inactives n’auront pas compensé l’affichage ou le masquage de l’en-tête).

  • indice L’index des onglets actifs, fourni par notre bibliothèque d’onglets vue React-native-tab
  • com/media//href2. La touche TABL’identifiant de l’onglet, fourni par notre bibliothèque d’onglets réaction-native-tab-view et transmis aux composants TabView individuels.

    com/media//href3. Il s’agit d’une carte d’identifiants d’onglets en références de composants à défilement (TabViews). Il sera utilisé plus tard pour mettre à jour passivement tous les décalages de défilement TabView inactifs.

    com/media//href4. Il s’agit d’une carte des identificateurs d’onglets avec leur position de défilement locale. Il sera utilisé pour comparer les scrollPositions mises en cache aux décalages d’en-tête pour déterminer si les décalages de défilement TabViews inactifs doivent être ajustés.

    com/media//hrefPour commencer à synchroniser les décalages de défilement Lorsque vous transmettez une méthode à la prop ref dans React, la méthode entrante est appelée avec une référence au composant. Nous prenons ensuite cette référence, ainsi qu’une table locale de TabView La touche TAB référence (transmise par réaction-native-tab-view ), et appelez notre trackRefméthode.

    com/media//hrefEnsuite Cela nous permet de savoir où tous nos onglets défilent (même les onglets inactifs) à un moment donné.

    com/media//hrefLa dernière étape pour synchroniser les décalages de défilement consiste à utiliser onMomentumScrollEndet onScrollEndDragévénements pour invoquer une méthode personnalisée que nous appelons syncScrollOffset.

    SyncScrollOffset parcourt les TabKeys inactifs et met à jour leurs décalages de défilement selon que l’en-tête défile dans ou hors de la vue. Cela garantira que chaque fois que vous glissez ou naviguez entre les TabViews, la hauteur de l’en-tête est toujours correctement maintenue.

    com/media//href

    Résumé

    Une partie importante de notre transition des technologies natives vers React Native a été non seulement de maintenir notre barre de qualité, mais aussi de l’augmenter. Cela se produit grâce à des investissements UX profonds, à notre système de conception multiplateforme, etc.

    nous recrutons !

    tels que l’intégration de milliers d’utilisateurs avec React Native et l’optimisation de React Native.

    Les sites tiers ne sont pas sous le contrôle de Coinbase, Inc. et de ses affiliés («Coinbase»), et Coinbase n’est pas responsable du contenu de tout site tiers, y compris, sans s’y limiter, tout lien contenu dans un tiers. Site de partie, ou toute modification ou mise à jour d’un site tiers. Coinbase n’est pas responsable de la diffusion sur le Web ou de toute autre forme de transmission reçue d’un site tiers. Coinbase ne vous fournit ces liens qu’à titre de commodité, et l’inclusion de tout lien n’implique pas l’approbation, l’approbation ou la recommandation par Coinbase du site ou de toute association avec ses opérateurs.

    Toutes les images fournies ici sont de Coinbase.

    La TabBar animée de Coinbase dans React Native a été publiée à l’origine dans The Coinbase Blog on Medium, où les gens poursuivent la conversation en mettant en évidence et en répondant à cette histoire.