El repositorio se ha trasladado a https://github.com/react Navigation/react Navigation/tree/main/packages/react-native-tab-view. Abra los problemas y extraiga las solicitudes allí.
Un componente de vista de pestaña multiplataforma para React Native. Implementado utilizando react-native-pager-view en Android e iOS, y PanRponder en Web, MacOS y Windows.
Para usar esta biblioteca, debe asegurarse de estar utilizando la versión correcta de React Native. Si está utilizando una versión de React Native que es inferior a 0.63 , deberá actualizarla antes de intentar usar esta biblioteca.
versión react-native-tab-view | Requerir la versión nativa react |
|---|---|
2.xx | < 0.63 |
3.xx | >= 0.63 |
Abra una terminal en la raíz del proyecto y ejecute:
yarn add react-native-tab-view Ahora necesitamos instalar react-native-pager-view si planea admitir iOS y Android.
Si está utilizando Expo, para asegurarse de obtener las versiones compatibles de las bibliotecas, ejecute:
expo install react-native-pager-viewSi no está usando Expo, ejecute lo siguiente:
yarn add react-native-pager-view¡Hemos terminado! Ahora puede construir y ejecutar la aplicación en su dispositivo/simulador.
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 } }
/>
) ;
}Prueba este ejemplo en bocadillo
El paquete exporta un componente TabView que es el que utilizaría para representar la vista de pestaña y un componente TabBar que es la implementación de barra de pestaña predeterminada.
TabViewComponente del contenedor responsable de representar y administrar pestañas. Sigue los estilos de diseño de materiales de forma predeterminada.
El uso básico se ve así:
< TabView
navigationState = { { index , routes } }
onIndexChange = { setIndex }
renderScene = { SceneMap ( {
first : FirstRoute ,
second : SecondRoute ,
} ) }
/> navigationState ( required )Estado para la vista de pestaña. El estado debe contener las siguientes propiedades:
index : un número que representa el índice de la ruta activa en la matriz routesroutes : una matriz que contiene una lista de objetos de ruta utilizados para representar las pestañasCada objeto de ruta debe contener las siguientes propiedades:
key : una clave única para identificar la ruta (requerida)title : Título para la ruta para mostrar en la barra de pestañasicon : icono para que la ruta se muestre en la barra de pestañaaccessibilityLabel : etiqueta de accesibilidad para el botón de pestañatestID : ID de prueba para el botón de pestañaEjemplo:
{
index : 1 ,
routes : [
{ key : 'music' , title : 'Music' } ,
{ key : 'albums' , title : 'Albums' } ,
{ key : 'recents' , title : 'Recents' } ,
{ key : 'purchased' , title : 'Purchased' } ,
]
} TabView es un componente controlado, lo que significa que el index debe actualizarse a través de la devolución de llamada onIndexChange .
onIndexChange ( required )La devolución de llamada que se llama en el cambio de pestaña, recibe el índice de la nueva pestaña como argumento. El estado de navegación debe actualizarse cuando se llama, de lo contrario el cambio se elimina.
renderScene ( required )Devolución de llamada que devuelve un elemento React para representar como la página para la pestaña. Recibe un objeto que contiene la ruta como argumento:
const renderScene = ( { route , jumpTo } ) => {
switch ( route . key ) {
case 'music' :
return < MusicRoute jumpTo = { jumpTo } /> ;
case 'albums' :
return < AlbumsRoute jumpTo = { jumpTo } /> ;
}
} ; Debe asegurarse de que sus rutas individuales implementen un shouldComponentUpdate para mejorar el rendimiento. Para facilitar la especificación de los componentes, puede usar el ayudante SceneMap .
SceneMap toma un objeto con la asignación de route.key Key para reaccionar componentes y devuelve una función para usar con renderScene Prop.
import { SceneMap } from 'react-native-tab-view' ;
...
const renderScene = SceneMap ( {
music : MusicRoute ,
albums : AlbumsRoute ,
} ) ; Especificar los componentes de esta manera es más fácil y se encarga de implementar un método shouldComponentUpdate .
Cada escena recibe los siguientes accesorios:
route : la ruta actual presentada por el componentejumpTo : método para saltar a otras pestañas, toma una route.key como argumentoposition : nodo animado que representa la posición actual El método jumpTo se puede usar para navegar a otras pestañas programáticamente:
this . props . jumpTo ( 'albums' ) ; Todas las escenas renderizadas con SceneMap se optimizan utilizando React.PureComponent y no vuelven a renderizar cuando los accesorios de los padres o los estados cambian. Si necesita más control sobre cómo se actualizan sus escenas (por ejemplo, activar un reiniciado incluso si la navigationState no cambió), use renderScene directamente en lugar de usar SceneMap .
IMPORTANTE: No pase las funciones en línea a SceneMap , por ejemplo, no haga lo siguiente:
SceneMap ( {
first : ( ) => < FirstRoute foo = { this . props . foo } /> ,
second : SecondRoute ,
} ) ;Siempre defina sus componentes en otra parte del nivel superior del archivo. Si pasa las funciones en línea, recreará el componente cada renderizado, lo que hará que toda la ruta desmonte y vuelva a montar cada cambio. Es muy malo para el rendimiento y también hará que se pierda cualquier estado local.
Si necesita pasar accesorios adicionales, use una función renderScene personalizado:
const renderScene = ( { route } ) => {
switch ( route . key ) {
case 'first' :
return < FirstRoute foo = { this . props . foo } /> ;
case 'second' :
return < SecondRoute /> ;
default :
return null ;
}
} ; renderTabBarDevolución de llamada que devuelve un elemento react personalizado para usar como barra de pestaña:
import { TabBar } from 'react-native-tab-view' ;
...
< TabView
renderTabBar = { props => < TabBar { ... props } /> }
. . .
/ >Si esto no se especifica, se representa la barra de pestaña predeterminada. Pase estos accesorios para personalizar la barra de pestaña predeterminada, proporcionar su propia barra de pestañas o deshabilitar la barra de pestañas por completo.
< TabView
renderTabBar = { ( ) => null }
. . .
/ > tabBarPosition Posición de la barra de pestañas en la vista de pestaña. Los valores posibles son 'top' e 'bottom' . El valor predeterminado es 'top' .
lazyFunción que toma un objeto con la ruta actual y devuelve un booleano para indicar si perezosamente representa las escenas.
Por defecto, todas las escenas se representan para proporcionar una experiencia de deslizamiento más suave. Pero es posible que desee diferir la representación de escenas desenfocadas hasta que el usuario las vea. Para habilitar la representación perezosa para una escena en particular, regrese true de getLazy para esa route :
< TabView
lazy = { ( { route } ) => route . name === 'Albums' }
. . .
/ > Cuando habilita la representación perezosa para una pantalla, generalmente tomará un tiempo para renderizar cuando se centre. Puede utilizar el accesorio renderLazyPlaceholder para personalizar lo que el usuario ve durante este corto período.
También puede pasar un booleano para habilitar perezoso para todas las escenas:
< TabView
lazy
/> lazyPreloadDistance Cuando se habilita lazy , puede especificar cuántas rutas adyacentes se deben precargar con este accesorio. Este valor predeterminado es 0 , lo que significa que las páginas perezosas se cargan a medida que entran en la ventana gráfica.
renderLazyPlaceholder La devolución de llamada que devuelve un elemento React personalizado para representar rutas que aún no se han representado. Recibe un objeto que contiene la ruta como argumento. El accesorio lazy también debe estar habilitado.
Esta vista generalmente solo se muestra durante una fracción de segundo. Mantenlo ligero.
Por defecto, esto hace que null .
keyboardDismissModeCadena que indica si el teclado se descarta en respuesta a un gesto de arrastre. Los valores posibles son:
'auto' (predeterminado): el teclado se descarta cuando cambia el índice.'on-drag' : el teclado se descarta cuando comienza una arrastre.'none' : los arrastre no descartan el teclado. swipeEnabled Booleano que indica si habilita los gestos de deslizamiento. Los gestos de deslizamiento están habilitados de forma predeterminada. Pasar false deshabilitará los gestos de deslizamiento, pero el usuario aún puede cambiar las pestañas presionando la barra de pestaña.
animationEnabledHabilita la animación al cambiar la pestaña. Por defecto es cierto.
onSwipeStartLa devolución de llamada que se llama cuando comienza el gesto de deslizamiento, es decir, el usuario toca la pantalla y la mueve.
onSwipeEndLa devolución de llamada que se llama cuando termina el gesto de deslizamiento, es decir, el usuario levanta el dedo de la pantalla después del gesto de deslizamiento.
initialLayoutObjeto que contiene la altura y el ancho iniciales de las pantallas. Pasar esto mejorará el rendimiento de renderizado inicial. Para la mayoría de las aplicaciones, este es un buen valor predeterminado:
< TabView
initialLayout = { { width : Dimensions . get ( 'window' ) . width } }
. . .
/ > sceneContainerStyleEstilo para aplicar a la vista envolviendo cada pantalla. Puede pasar esto para anular algunos estilos predeterminados, como el recorte de desbordamiento:
pagerStyleEstilo para aplicar a la vista de buscapersonas envolviendo todas las escenas.
styleEstilo para aplicar al contenedor de vista de pestañas.
TabBar Barra de pestaña temática de diseño de material. Para personalizar la barra de pestaña, necesitaría usar el accesorio renderTabBar de TabView para representar el TabBar y pasar accesorios adicionales.
Por ejemplo, para personalizar el color del indicador y el color de fondo de la barra de pestaña, puede pasar los accesorios indicatorStyle y style al TabBar respectivamente:
const renderTabBar = props => (
< TabBar
{ ... props }
indicatorStyle = { { backgroundColor : 'white' } }
style = { { backgroundColor : 'pink' } }
/>
) ;
//...
return (
< TabView
renderTabBar = { renderTabBar }
. . .
/ >
);getLabelText Función que toma un objeto con la ruta actual y devuelve el texto de la etiqueta para la pestaña. Usa route.title de forma predeterminada.
< TabBar
getLabelText = { ( { route } ) => route . title }
. . .
/ > getAccessible Función que toma un objeto con la ruta actual y devuelve un booleano para indicar si marcar una pestaña como accessible . El valor predeterminado es true .
getAccessibilityLabel Función que toma un objeto con la ruta actual y devuelve una etiqueta de accesibilidad para el botón de pestaña. Usa route.accessibilityLabel Por defecto si se especifica, de lo contrario usa el título de ruta.
< TabBar
getAccessibilityLabel = { ( { route } ) => route . accessibilityLabel }
. . .
/ > getTestID Función que toma un objeto con la ruta actual y devuelve un ID de prueba para el botón de pestaña para localizar este botón de pestaña en las pruebas. Usa route.testID de forma predeterminada.
< TabBar
getTestID = { ( { route } ) => route . testID }
. . .
/ > renderIconFunción que toma un objeto con la ruta actual, el estado y el color enfocado y devuelve un elemento react personalizado para ser utilizado como icono.
< TabBar
renderIcon = { ( { route , focused , color } ) => (
< Icon
name = { focused ? 'albums' : 'albums-outlined' }
color = { color }
/>
) }
. . .
/ > renderLabelFunción que toma un objeto con la ruta actual, el estado y el color enfocado y devuelve un elemento react personalizado para ser utilizado como etiqueta.
< TabBar
renderLabel = { ( { route , focused , color } ) => (
< Text style = { { color , margin : 8 } } >
{ route . title }
</ Text >
) }
. . .
/ > renderTabBarItem Función que toma un objeto TabBarItemProps y devuelve un elemento React personalizado para usarse como un botón de pestaña.
renderIndicatorFunción que toma un objeto con la ruta actual y devuelve un elemento react personalizado para ser utilizado como un indicador de pestaña.
renderBadgeFunción que toma un objeto con la ruta actual y devuelve un elemento react personalizado para ser utilizado como insignia.
onTabPressFunción para ejecutar en la pestaña Presione. Recibe la escena de la pestaña presionada, útil para cosas como desplazarse hasta la parte superior.
Por defecto, la pestaña Presione también cambia la pestaña. Para prevenir este comportamiento, puede llamar preventDefault :
< TabBar
onTabPress = { ( { route , preventDefault } ) => {
if ( route . key === 'home' ) {
preventDefault ( ) ;
// Do something else
}
} }
. . .
/ > onTabLongPressFunción para ejecutar en Tab Long Press, use para mostrar un menú con más opciones
activeColorColor personalizado para icono y etiqueta en la pestaña Activa.
inactiveColorColor personalizado para icono y etiqueta en la pestaña Inactiva.
pressColorColor para el material Ripple (Android> = 5.0 solamente).
pressOpacityOpacidad para la pestaña presionada (iOS y Android <5.0 solamente).
scrollEnabledBooleano indicando si hacer que la barra de pestaña se desplazara.
Si establece scrollEnabled en true , también debe especificar un width en tabStyle para mejorar el render inicial.
bouncesBooleano que indica si la barra de pestaña rebota al desplazarse.
tabStyleEstilo para aplicar a los elementos de pestaña individuales en la barra de pestaña.
Por defecto, todos los elementos de pestaña ocupan el mismo ancho precalculado en función del ancho del contenedor. Si desea que tomen su ancho original, puede especificar width: 'auto' en tabStyle .
indicatorStyleEstilo para aplicar al indicador activo.
indicatorContainerStyleEstilo para aplicar a la vista del contenedor para el indicador.
labelStyleEstilo para aplicar a la etiqueta del elemento de pestaña.
contentContainerStyleEstilo para aplicar al contenedor interno para pestañas.
styleEstilo para aplicar al contenedor de barra de pestaña.
gapDefina un espacio entre las pestañas.
testIDID de prueba para el TabBar. Se puede usar para desplazar la barra de pestaña en las pruebas
Si desea integrar la vista de pestaña con el sistema de navegación de React Navigation, por ejemplo, desea poder navegar a una pestaña usando navigation.navigate , etc., puede usar las siguientes integraciones oficiales:
Tenga en cuenta que algunas funcionalidades no están disponibles con la integración de React Navigation 4 debido a las limitaciones en la navegación React. Por ejemplo, es posible cambiar dinámicamente las pestañas renderizadas.
La función renderScene se llama cada vez que cambia el índice. Si su función renderScene es costosa, es una buena idea mover cada ruta a un componente separado si no dependen del índice, y use shouldComponentUpdate o React.memo
Por ejemplo, en lugar de:
const renderScene = ( { route } ) => {
switch ( route . key ) {
case 'home' :
return (
< View style = { styles . page } >
< Avatar />
< NewsFeed />
</ View >
) ;
default :
return null ;
}
} ;Haz lo siguiente:
const renderScene = ( { route } ) => {
switch ( route . key ) {
case 'home' :
return < HomeComponent /> ;
default :
return null ;
}
} ; Donde <HomeComponent /> es un PureComponent si está utilizando componentes de clase:
export default class HomeComponent extends React . PureComponent {
render ( ) {
return (
< View style = { styles . page } >
< Avatar />
< NewsFeed />
</ View >
) ;
}
} O, envuelto en React.memo si está utilizando componentes de la función:
function HomeComponent ( ) {
return (
< View style = { styles . page } >
< Avatar />
< NewsFeed />
</ View >
) ;
}
export default React . memo ( HomeComponent ) ;Necesitamos medir el ancho del contenedor y, por lo tanto, debemos esperar antes de representar algunos elementos en la pantalla. Si conoce el ancho inicial por adelantado, puede pasarlo y no tendremos que esperar para medirlo. La mayoría de las veces, es solo el ancho de la ventana.
Por ejemplo, pase el siguiente initialLayout a TabView :
const initialLayout = {
height : 0 ,
width : Dimensions . get ( 'window' ) . width ,
} ;La vista de pestaña aún reaccionará a los cambios en la dimensión y se ajustará en consecuencia para acomodar cosas como el cambio de orientación.
Si tiene una gran cantidad de rutas, especialmente imágenes, puede retrasar mucho la animación. En su lugar, puede representar un número limitado de rutas.
Por ejemplo, haga lo siguiente para representar solo 2 rutas en cada lado:
const renderScene = ( { route } ) => {
if ( Math . abs ( index - routes . indexOf ( route ) ) > 2 ) {
return < View /> ;
}
return < MySceneComponent route = { route } /> ;
} ; Anidar la TabView dentro de una ScrollView vertical deshabilitará las optimizaciones en los componentes FlatList representadas dentro de TabView . Así que evite hacerlo si es posible.
lazy y renderLazyPlaceholder para renderizar las rutas según sea necesario La opción lazy está deshabilitada de forma predeterminada para proporcionar una experiencia de conmutación de pestañas más suave, pero puede habilitarla y proporcionar un componente de marcador de posición para una mejor experiencia de carga perezosa. Habilitar lazy puede mejorar el rendimiento de la carga inicial al hacer rutas solo cuando aparecen a la vista. Consulte la referencia de PROP para obtener más detalles.
Mientras se desarrolla, puede ejecutar la aplicación Ejemplo para probar sus cambios.
Asegúrese de que su código pase TypeScript y Eslint. Ejecute lo siguiente para verificar:
yarn typescript
yarn lintPara corregir errores de formato, ejecute lo siguiente:
yarn lint -- --fixRecuerde agregar pruebas para su cambio si es posible.