Le repo a été déplacé vers https://github.com/react-navigation/react-navigation/tree/main/packages/react-native-tab-view. Veuillez ouvrir des problèmes et y retirer les demandes.
Un composant de vue d'onglet multiplateforme pour React Native. Implémenté à l'aide de react-native-pager-view sur Android & iOS, et PanResponder sur le Web, le macOS et Windows.
Pour utiliser cette bibliothèque, vous devez vous assurer que vous utilisez la version correcte de React Native. Si vous utilisez une version de React Native qui est inférieure à 0.63 vous devrez la mettre à niveau avant d'essayer d'utiliser cette bibliothèque.
version react-native-tab-view | Version native react requise |
|---|---|
2.xx | < 0.63 |
3.xx | >= 0.63 |
Ouvrez un terminal dans la racine du projet et exécutez:
yarn add react-native-tab-view Nous devons maintenant installer react-native-pager-view si vous prévoyez de prendre en charge iOS et Android.
Si vous utilisez Expo, pour vous assurer que vous obtenez les versions compatibles des bibliothèques, exécutez:
expo install react-native-pager-viewSi vous n'utilisez pas Expo, exécutez ce qui suit:
yarn add react-native-pager-viewNous avons fini! Vous pouvez maintenant créer et exécuter l'application sur votre appareil / simulateur.
import * as React from 'react' ;
import { View , useWindowDimensions } from 'react-native' ;
import { TabView , SceneMap } from 'react-native-tab-view' ;
const FirstRoute = ( ) => (
< View style = { { flex : 1 , backgroundColor : '#ff4081' } } />
) ;
const SecondRoute = ( ) => (
< View style = { { flex : 1 , backgroundColor : '#673ab7' } } />
) ;
const renderScene = SceneMap ( {
first : FirstRoute ,
second : SecondRoute ,
} ) ;
export default function TabViewExample ( ) {
const layout = useWindowDimensions ( ) ;
const [ index , setIndex ] = React . useState ( 0 ) ;
const [ routes ] = React . useState ( [
{ key : 'first' , title : 'First' } ,
{ key : 'second' , title : 'Second' } ,
] ) ;
return (
< TabView
navigationState = { { index , routes } }
renderScene = { renderScene }
onIndexChange = { setIndex }
initialLayout = { { width : layout . width } }
/>
) ;
}Essayez cet exemple sur Snack
Le package exporte un composant TabView qui est celui que vous utiliserez pour rendre la vue sur l'onglet, et un composant TabBar qui est l'implémentation de la barre d'onglet par défaut.
TabViewComposant de conteneur responsable du rendu et de la gestion des onglets. Suit les styles de conception de matériaux par défaut.
L'utilisation de base ressemble à ceci:
< TabView
navigationState = { { index , routes } }
onIndexChange = { setIndex }
renderScene = { SceneMap ( {
first : FirstRoute ,
second : SecondRoute ,
} ) }
/> navigationState ( required )État pour la vue d'onglet. L'état doit contenir les propriétés suivantes:
index : un nombre représentant l'index de la route active dans le tableau routesroutes : un tableau contenant une liste d'objets d'itinéraire utilisés pour rendre les ongletsChaque objet d'itinéraire doit contenir les propriétés suivantes:
key : une clé unique pour identifier l'itinéraire (requis)title : Titre de l'itinéraire à afficher dans la barre d'ongleticon : icône de l'itinéraire à afficher dans la barre d'ongletaccessibilityLabel : Étiquette d'accessibilité pour le bouton TabtestID : ID de test pour le bouton d'ongletExemple:
{
index : 1 ,
routes : [
{ key : 'music' , title : 'Music' } ,
{ key : 'albums' , title : 'Albums' } ,
{ key : 'recents' , title : 'Recents' } ,
{ key : 'purchased' , title : 'Purchased' } ,
]
} TabView est un composant contrôlé, ce qui signifie que l' index doit être mis à jour via le rappel onIndexChange .
onIndexChange ( required )Le rappel qui est appelé sur le changement d'onglet, reçoit l'index du nouvel onglet en tant qu'argument. L'état de navigation doit être mis à jour lorsqu'il s'appelle, sinon le changement est abandonné.
renderScene ( required )Rappel qui renvoie un élément de réact à Render comme page pour l'onglet. Reçoit un objet contenant l'itinéraire comme argument:
const renderScene = ( { route , jumpTo } ) => {
switch ( route . key ) {
case 'music' :
return < MusicRoute jumpTo = { jumpTo } /> ;
case 'albums' :
return < AlbumsRoute jumpTo = { jumpTo } /> ;
}
} ; Vous devez vous assurer que vos routes individuelles implémentent un shouldComponentUpdate pour améliorer les performances. Pour faciliter la spécification des composants, vous pouvez utiliser l'assistance SceneMap .
SceneMap prend un objet avec le mappage de route.key pour réagir les composants et renvoie une fonction à utiliser avec renderScene Prop.
import { SceneMap } from 'react-native-tab-view' ;
...
const renderScene = SceneMap ( {
music : MusicRoute ,
albums : AlbumsRoute ,
} ) ; La spécification des composants de cette façon est plus facile et s'occupe de la mise en œuvre d'une méthode shouldComponentUpdate .
Chaque scène reçoit les accessoires suivants:
route : l'itinéraire actuel rendu par le composantjumpTo : Méthode pour passer à d'autres onglets, prend un route.keyposition : nœud animé qui représente la position actuelle La méthode jumpTo peut être utilisée pour naviguer vers d'autres onglets par programme:
this . props . jumpTo ( 'albums' ) ; Toutes les scènes rendues avec SceneMap sont optimisées à l'aide de React.PureComponent et ne rendent pas lorsque les accessoires ou états des parents changent. Si vous avez besoin de plus de contrôle sur la façon dont vos scènes se mettent à jour (par exemple - déclenchant une rediffusion même si le navigationState n'a pas changé), utilisez renderScene directement au lieu d'utiliser SceneMap .
IMPORTANT: Ne passez pas les fonctions en ligne à SceneMap , par exemple, ne faites pas ce qui suit:
SceneMap ( {
first : ( ) => < FirstRoute foo = { this . props . foo } /> ,
second : SecondRoute ,
} ) ;Définissez toujours vos composants ailleurs au niveau supérieur du fichier. Si vous passez des fonctions en ligne, il recréera le composant chaque rendu, ce qui provoquera toute la route pour déboucher et remanierra chaque changement. C'est très mauvais pour les performances et entraînera également la perte de tout État local.
Si vous devez transmettre des accessoires supplémentaires, utilisez une fonction renderScene personnalisée:
const renderScene = ( { route } ) => {
switch ( route . key ) {
case 'first' :
return < FirstRoute foo = { this . props . foo } /> ;
case 'second' :
return < SecondRoute /> ;
default :
return null ;
}
} ; renderTabBarRappel qui renvoie un élément de réaction personnalisé à utiliser comme barre d'onglet:
import { TabBar } from 'react-native-tab-view' ;
...
< TabView
renderTabBar = { props => < TabBar { ... props } /> }
. . .
/ >Si cela n'est pas spécifié, la barre d'onglet par défaut est rendue. Vous passez ces accessoires pour personnaliser la barre d'onglet par défaut, fournir votre propre barre d'onglet ou désactiver complètement la barre d'onglet.
< TabView
renderTabBar = { ( ) => null }
. . .
/ > tabBarPosition Position de la barre d'onglet dans la vue Tab. Les valeurs possibles sont 'top' et 'bottom' . Par défaut est 'top' .
lazyFonction qui prend un objet avec l'itinéraire actuel et renvoie un booléen pour indiquer si pour rendre les scènes paresseusement.
Par défaut, toutes les scènes sont rendues pour offrir une expérience de balayage plus lisse. Mais vous voudrez peut-être différer le rendu des scènes non focalisées jusqu'à ce que l'utilisateur les voit. Pour permettre le rendu paresseux pour une scène particulière, revenez true de getLazy pour cette route :
< TabView
lazy = { ( { route } ) => route . name === 'Albums' }
. . .
/ > Lorsque vous activez le rendu paresseux pour un écran, il faudra généralement un certain temps pour rendre lorsqu'il se concentre. Vous pouvez utiliser l'hélice renderLazyPlaceholder pour personnaliser ce que l'utilisateur voit pendant cette courte période.
Vous pouvez également passer un booléen pour activer paresseux pour toutes les scènes:
< TabView
lazy
/> lazyPreloadDistance Lorsque lazy est activé, vous pouvez spécifier le nombre de routes adjacentes préchargées avec cet accessoire. Cette valeur est par défaut à 0 ce qui signifie que les pages paresseuses sont chargées à mesure qu'elles entrent dans la fenêtre.
renderLazyPlaceholder Rappel qui renvoie un élément de réaction personnalisé à rendre pour des itinéraires qui n'ont pas encore été rendus. Reçoit un objet contenant l'itinéraire comme argument. L' lazy paresseuse doit également être activée.
Cette vue est généralement affichée uniquement pour une fraction de seconde. Gardez-le léger.
Par défaut, cela rend null .
keyboardDismissModeChaîne indiquant si le clavier est rejeté en réponse à un geste de traînée. Les valeurs possibles sont:
'auto' (par défaut): Le clavier est rejeté lorsque l'index change.'on-drag' : le clavier est rejeté lorsqu'un drag commence.'none' : les traînées ne rejettent pas le clavier. swipeEnabled Booléen indiquant l'opportunité d'activer les gestes de balayage. Les gestes de balayage sont activés par défaut. Passer false désactivera les gestes de balayage, mais l'utilisateur peut toujours changer d'onglets en appuyant sur la barre d'onglet.
animationEnabledPermet l'animation lors de la modification de l'onglet. Par défaut, c'est vrai.
onSwipeStartLe rappel qui est appelé lorsque le geste de balayage démarre, c'est-à-dire que l'utilisateur touche l'écran et le déplace.
onSwipeEndLe rappel qui est appelé lorsque le geste de balayage se termine, c'est-à-dire que l'utilisateur soulève son doigt de l'écran après le geste de balayage.
initialLayoutObjet contenant la hauteur et la largeur initiales des écrans. La réussite améliorera les performances de rendu initiales. Pour la plupart des applications, c'est un bon défaut:
< TabView
initialLayout = { { width : Dimensions . get ( 'window' ) . width } }
. . .
/ > sceneContainerStyleStyle à appliquer à la vue Emballage de chaque écran. Vous pouvez le faire passer pour remplacer certains styles par défaut tels que la décollement de débordement:
pagerStyleStyle à appliquer à la vue du téléavertisseur enroulant toutes les scènes.
styleStyle à appliquer au conteneur de la vue d'onglet.
TabBar Bar à onglet sur le thème de la conception de matériau. Pour personnaliser la barre d'onglet, vous devrez utiliser le condentabbar renderTabBar de TabView pour rendre le TabBar et passer des accessoires supplémentaires.
Par exemple, pour personnaliser la couleur de l'indicateur et la couleur d'arrière-plan de la barre d'onglet, vous pouvez passer respectivement les accessoires de style indicatorStyle et style au TabBar :
const renderTabBar = props => (
< TabBar
{ ... props }
indicatorStyle = { { backgroundColor : 'white' } }
style = { { backgroundColor : 'pink' } }
/>
) ;
//...
return (
< TabView
renderTabBar = { renderTabBar }
. . .
/ >
);getLabelText Fonction qui prend un objet avec l'itinéraire actuel et renvoie le texte de l'étiquette pour l'onglet. Utilise route.title par défaut.
< TabBar
getLabelText = { ( { route } ) => route . title }
. . .
/ > getAccessible Fonction qui prend un objet avec l'itinéraire actuel et renvoie un booléen pour indiquer s'il faut marquer un onglet comme accessible . Par défaut est true .
getAccessibilityLabel Fonction qui prend un objet avec l'itinéraire actuel et renvoie une étiquette d'accessibilité pour le bouton Tab. Utilise route.accessibilityLabel par défaut si elle est spécifiée, autrement utilise le titre de route.
< TabBar
getAccessibilityLabel = { ( { route } ) => route . accessibilityLabel }
. . .
/ > getTestID Fonction qui prend un objet avec l'itinéraire actuel et renvoie un ID de test pour le bouton Tab pour localiser ce bouton d'onglet dans les tests. Utilise route.testID par défaut.
< TabBar
getTestID = { ( { route } ) => route . testID }
. . .
/ > renderIconFonction qui prend un objet avec l'itinéraire actuel, l'état ciblé et la couleur et renvoie un élément de réaction personnalisé à utiliser comme icône.
< TabBar
renderIcon = { ( { route , focused , color } ) => (
< Icon
name = { focused ? 'albums' : 'albums-outlined' }
color = { color }
/>
) }
. . .
/ > renderLabelFonction qui prend un objet avec l'itinéraire actuel, l'état focalisé et la couleur et renvoie un élément de réaction personnalisé à utiliser comme étiquette.
< TabBar
renderLabel = { ( { route , focused , color } ) => (
< Text style = { { color , margin : 8 } } >
{ route . title }
</ Text >
) }
. . .
/ > renderTabBarItem Fonction qui prend un objet TabBarItemProps et renvoie un élément de réaction personnalisé à utiliser comme bouton d'onglet.
renderIndicatorFonction qui prend un objet avec l'itinéraire actuel et renvoie un élément de réaction personnalisé à utiliser comme indicateur d'onglet.
renderBadgeFonction qui prend un objet avec l'itinéraire actuel et renvoie un élément de réaction personnalisé à utiliser comme badge.
onTabPressFonction à exécuter sur la pression sur l'onglet. Il reçoit la scène de l'onglet pressé, utile pour que des choses comme le parchemin de haut.
Par défaut, l'onglet Appuyez également sur l'onglet. Pour éviter ce comportement, vous pouvez appeler preventDefault :
< TabBar
onTabPress = { ( { route , preventDefault } ) => {
if ( route . key === 'home' ) {
preventDefault ( ) ;
// Do something else
}
} }
. . .
/ > onTabLongPressFonction à exécuter sur Tab Long appuyez sur, utilisez des choses comme afficher un menu avec plus d'options
activeColorCouleur personnalisée pour l'icône et étiqueter dans l'onglet Active.
inactiveColorCouleur personnalisée pour l'icône et étiqueter dans l'onglet inactif.
pressColorCouleur pour le matériau Ripple (Android> = 5,0 seulement).
pressOpacityOPCITALE POUR TAB PRIESSED (iOS et Android <5.0 uniquement).
scrollEnabledBooléen indiquant s'il faut faire défiler la barre d'onglet.
Si vous définissez scrollEnabled sur true , vous devez également spécifier une width dans tabStyle pour améliorer le rendu initial.
bouncesBooléen indiquant si la barre d'onglet rebondit lors du défilement.
tabStyleStyle à appliquer aux éléments de l'onglet individuels dans la barre d'onglet.
Par défaut, tous les éléments d'onglet prennent la même largeur pré-calculée en fonction de la largeur du conteneur. Si vous voulez qu'ils prennent leur largeur d'origine, vous pouvez spécifier width: 'auto' dans tabStyle .
indicatorStyleStyle à appliquer à l'indicateur actif.
indicatorContainerStyleStyle à appliquer à la vue du conteneur pour l'indicateur.
labelStyleStyle à appliquer à l'étiquette des éléments d'onglet.
contentContainerStyleStyle à appliquer au conteneur intérieur pour les onglets.
styleStyle à appliquer au conteneur de la barre d'onglet.
gapDéfinissez un espacement entre les onglets.
testIDID de test pour le tabbar. Peut être utilisé pour faire défiler la barre d'onglet dans les tests
Si vous souhaitez intégrer la vue d'onglet avec le système de navigation de React Navigation, par exemple, vous souhaitez pouvoir naviguer vers un onglet à l'aide navigation.navigate , etc., vous pouvez utiliser les intégrations officielles suivantes:
Notez que certaines fonctionnalités ne sont pas disponibles avec l'intégration React Navigation 4 en raison des limites de la navigation React. Par exemple, il est possible de modifier dynamiquement les onglets rendus.
La fonction renderScene est appelée chaque fois que l'indice change. Si votre fonction renderScene est coûteuse, c'est une bonne idée de déplacer chaque itinéraire vers un composant distinct s'ils ne dépendent pas de l'index et utilisent shouldComponentUpdate ou React.memo dans vos composants d'itinéraire pour éviter les retendeurs inutiles.
Par exemple, au lieu de:
const renderScene = ( { route } ) => {
switch ( route . key ) {
case 'home' :
return (
< View style = { styles . page } >
< Avatar />
< NewsFeed />
</ View >
) ;
default :
return null ;
}
} ;Procédez comme suit:
const renderScene = ( { route } ) => {
switch ( route . key ) {
case 'home' :
return < HomeComponent /> ;
default :
return null ;
}
} ; Où <HomeComponent /> est un PureComponent si vous utilisez des composants de classe:
export default class HomeComponent extends React . PureComponent {
render ( ) {
return (
< View style = { styles . page } >
< Avatar />
< NewsFeed />
</ View >
) ;
}
} Ou, enveloppé dans React.memo si vous utilisez des composants de fonction:
function HomeComponent ( ) {
return (
< View style = { styles . page } >
< Avatar />
< NewsFeed />
</ View >
) ;
}
export default React . memo ( HomeComponent ) ;Nous devons mesurer la largeur du conteneur et donc devons attendre avant de rendre certains éléments à l'écran. Si vous connaissez la largeur initiale à l'avance, vous pouvez la transmettre et nous n'aurons pas besoin d'attendre la mesure. La plupart du temps, c'est juste la largeur de la fenêtre.
Par exemple, passez le initialLayout suivant à TabView :
const initialLayout = {
height : 0 ,
width : Dimensions . get ( 'window' ) . width ,
} ;La vue d'onglet réagira toujours aux modifications de la dimension et s'ajustera en conséquence pour s'adapter à des choses comme le changement d'orientation.
Si vous avez un grand nombre de voies, en particulier des images, cela peut ralentir beaucoup l'animation. Vous pouvez plutôt rendre un nombre limité d'itinéraires.
Par exemple, procédez comme suit pour ne rendre que 2 routes de chaque côté:
const renderScene = ( { route } ) => {
if ( Math . abs ( index - routes . indexOf ( route ) ) > 2 ) {
return < View /> ;
}
return < MySceneComponent route = { route } /> ;
} ; Le nidification du TabView à l'intérieur d'un ScrollView vertical désactivera les optimisations dans les composants FlatList rendus à l'intérieur du TabView . Alors évitez de le faire si possible.
lazy et renderLazyPlaceholder pour rendre les routes au besoin L'option lazy est désactivée par défaut pour offrir une expérience de commutation d'onglet plus lisse, mais vous pouvez l'activer et fournir un composant d'espace réservé pour une meilleure expérience de chargement paresseuse. L'activation lazy peut améliorer les performances de charge initiale en rendant les itinéraires uniquement lorsqu'ils apparaissent. Reportez-vous à la référence des accessoires pour plus de détails.
Pendant le développement, vous pouvez exécuter l'application d'exemple pour tester vos modifications.
Assurez-vous que votre code passe TypeScript et Eslint. Exécutez ce qui suit pour vérifier:
yarn typescript
yarn lintPour corriger les erreurs de formatage, exécutez ce qui suit:
yarn lint -- --fixN'oubliez pas d'ajouter des tests pour votre modification si possible.