存儲庫已移至https://github.com/react-navigation/react-navigation/tree/main/main/packages/react-native-tab-view。請打開問題並在那裡提取請求。
React Native的跨平台選項卡視圖組件。使用Android&iOS上的react-native-pager-view以及Web,MacOS和Windows上的Panresponder實施。
要使用此庫,您需要確保使用正確版本的React Native。如果您使用的是低於0.63的React本機版本,則需要在嘗試使用此庫之前升級該版本。
react-native-tab-view版本 | 必需的反應本機版本 |
|---|---|
2.xx | < 0.63 |
3.xx | >= 0.63 |
在項目根中打開終端並運行:
yarn add react-native-tab-view現在,如果您打算支持iOS和Android,我們需要安裝react-native-pager-view 。
如果您使用的是Expo,請確保您獲得庫的兼容版本,請運行:
expo install react-native-pager-view如果您不使用博覽會,請運行以下內容:
yarn add react-native-pager-view我們完成了!現在,您可以在設備/模擬器上構建並運行該應用程序。
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 } }
/>
) ;
}在零食上嘗試此示例
該軟件包導出一個TabView組件,該組件是您用來渲染Tab View的一個組件,而TabBar組件是默認的Tab bar實現。
TabView負責渲染和管理選項卡的容器組件。默認情況下遵循材料設計樣式。
基本用法如下:
< TabView
navigationState = { { index , routes } }
onIndexChange = { setIndex }
renderScene = { SceneMap ( {
first : FirstRoute ,
second : SecondRoute ,
} ) }
/> navigationState ( required )標籤視圖的狀態。該州應包含以下屬性:
index :代表routes數組中活動路線索引的數字routes :包含用於渲染選項卡的路由對象列表的數組每個路由對象應包含以下屬性:
key :識別路線的獨特鍵(必需)title :在標籤欄中顯示路線的標題icon :在標籤欄中顯示路由的圖標accessibilityLabel :“選項卡”按鈕的可訪問性標籤testID :標籤按鈕的測試ID例子:
{
index : 1 ,
routes : [
{ key : 'music' , title : 'Music' } ,
{ key : 'albums' , title : 'Albums' } ,
{ key : 'recents' , title : 'Recents' } ,
{ key : 'purchased' , title : 'Purchased' } ,
]
} TabView是一個受控組件,這意味著需要通過onIndexChange回調更新index 。
onIndexChange ( required )在選項卡更改上調用的回調,將新選項卡的索引作為參數接收。導航狀態在被調用時需要更新,否則更改將被刪除。
renderScene ( required )回調將React元素返回到渲染作為標籤的頁面。接收包含路由的對像作為參數:
const renderScene = ( { route , jumpTo } ) => {
switch ( route . key ) {
case 'music' :
return < MusicRoute jumpTo = { jumpTo } /> ;
case 'albums' :
return < AlbumsRoute jumpTo = { jumpTo } /> ;
}
} ;您需要確保您的各個路線實現了shouldComponentUpdate以提高性能。為了使指定組件更容易,您可以使用SceneMap助手。
SceneMap採用route.key映射的對象。關鍵以反應組件並返回一個函數以與renderScene Prop一起使用。
import { SceneMap } from 'react-native-tab-view' ;
...
const renderScene = SceneMap ( {
music : MusicRoute ,
albums : AlbumsRoute ,
} ) ;以這種方式指定組件很容易,並且會照顧實現shouldComponentUpdate方法。
每個場景都會收到以下道具:
route :組件渲染的當前路線jumpTo :跳到其他選項卡的方法,採用route.key 。position :代表當前位置的動畫節點jumpTo方法可用於編程導航到其他選項卡:
this . props . jumpTo ( 'albums' ) ;使用React.PureComponent優化了使用SceneMap呈現的所有場景,並且在父母的道具或狀態更改時,請勿重新渲染。如果您需要更多地控制場景如何更新(例如,即使navigationState未更改即使觸發重新渲染),請直接使用renderScene而不是使用SceneMap 。
重要:例如,不要將內聯函數傳遞給SceneMap ,不要執行以下操作:
SceneMap ( {
first : ( ) => < FirstRoute foo = { this . props . foo } /> ,
second : SecondRoute ,
} ) ;始終在文件的頂級其他地方定義您的組件。如果通過內聯功能,它將重新創建每個渲染的組件,這將導致整個路線卸載並重新啟動所有更改。這對於性能非常糟糕,也會導致任何當地國家丟失。
如果您需要傳遞其他道具,請使用自定義renderScene函數:
const renderScene = ( { route } ) => {
switch ( route . key ) {
case 'first' :
return < FirstRoute foo = { this . props . foo } /> ;
case 'second' :
return < SecondRoute /> ;
default :
return null ;
}
} ; renderTabBar返回自定義反應元件的回調用作標籤欄:
import { TabBar } from 'react-native-tab-view' ;
...
< TabView
renderTabBar = { props => < TabBar { ... props } /> }
. . .
/ >如果未指定此功能,則呈現默認的選項卡欄。您通過此道具自定義默認的選項卡欄,提供自己的選項卡欄,或完全禁用標籤欄。
< TabView
renderTabBar = { ( ) => null }
. . .
/ > tabBarPosition標籤欄的位置在標籤視圖中。可能的值是'top'和'bottom' 。默認為'top' 。
lazy將對象帶有當前路線並返回布爾值以指示是否懶洋洋地渲染場景。
默認情況下,所有場景都呈現為提供平滑的滑動體驗。但是,您可能需要推遲未關注場景的渲染,直到用戶看到它們為止。要啟用特定場景的懶惰渲染, true從getLazy返回該route :
< TabView
lazy = { ( { route } ) => route . name === 'Albums' }
. . .
/ >當您為屏幕啟用懶惰渲染時,通常需要一些時間才能渲染。您可以使用renderLazyPlaceholder Prop來自定義用戶在此短期內看到的內容。
您也可以通過布爾值來為所有場景延遲懶惰:
< TabView
lazy
/> lazyPreloadDistance啟用lazy後,您可以指定使用此道具預裝多少個相鄰路線。此值默認為0 ,這意味著懶惰頁面進入視口。
renderLazyPlaceholder回調將自定義React元素返回到尚未渲染的路線的渲染。接收一個包含路由作為參數的對象。還需要啟用lazy道具。
這種視圖通常僅顯示一秒鐘。保持輕巧。
默認情況下,這使得null 。
keyboardDismissMode字符串指示鍵盤是否因響應阻力手勢而被解僱。可能的值是:
'auto' (默認值):索引更改時鍵盤被解散。'on-drag' :拖動開始時會忽略鍵盤。'none' :拖動不會解散鍵盤。 swipeEnabled布爾值指示是否啟用滑動手勢。默認情況下啟用滑動手勢。通過false將禁用滑動手勢,但是用戶仍然可以通過按TAB欄來切換選項卡。
animationEnabled更改選項卡時啟用動畫。默認情況下是真的。
onSwipeStart當滑動手勢啟動時稱為回調,即用戶觸摸屏幕並將其移動。
onSwipeEnd當滑動手勢結束時稱為回調,即用戶在滑動手勢後從屏幕上抬起手指。
initialLayout包含屏幕的初始高度和寬度的對象。通過這將改善最初的渲染性能。對於大多數應用程序,這是一個很好的默認值:
< TabView
initialLayout = { { width : Dimensions . get ( 'window' ) . width } }
. . .
/ > sceneContainerStyle樣式適用於視圖包裝每個屏幕。您可以將其傳遞給一些默認樣式,例如溢出剪輯:
pagerStyle適用於Pager View包裝所有場景的樣式。
style適用於選項卡視圖容器的樣式。
TabBar材料設計主題標籤欄。要自定義標籤欄,您需要使用TabView的renderTabBar Prop渲染TabBar並傳遞其他道具。
例如,要自定義指示器顏色和標籤欄背景顏色,您可以分別將indicatorStyle和style道具傳遞給TabBar :
const renderTabBar = props => (
< TabBar
{ ... props }
indicatorStyle = { { backgroundColor : 'white' } }
style = { { backgroundColor : 'pink' } }
/>
) ;
//...
return (
< TabView
renderTabBar = { renderTabBar }
. . .
/ >
);getLabelText使用當前路由的對象並返回選項卡的標籤文本。默認情況下使用route.title 。
< TabBar
getLabelText = { ( { route } ) => route . title }
. . .
/ > getAccessible函數將對象帶有當前路由,並返回布爾值,以指示是否將選項卡標記為accessible 。默認為true 。
getAccessibilityLabel使用當前路由的對象,並返回“選項卡”按鈕的可訪問性標籤。使用route.accessibilityLabel默認情況下,如果指定了默認情況,則使用路由標題。
< TabBar
getAccessibilityLabel = { ( { route } ) => route . accessibilityLabel }
. . .
/ > getTestID使用當前路由的對象,並返回“選項卡”按鈕的測試ID,以在測試中找到此選項卡按鈕。默認情況下使用route.testID 。
< TabBar
getTestID = { ( { route } ) => route . testID }
. . .
/ > renderIcon將對象帶有當前路由,重點狀態和顏色的功能,並返回自定義反應元素以用作圖標。
< TabBar
renderIcon = { ( { route , focused , color } ) => (
< Icon
name = { focused ? 'albums' : 'albums-outlined' }
color = { color }
/>
) }
. . .
/ > renderLabel具有當前路由,重點狀態和顏色的對象的功能,並返回自定義反應元素以用作標籤。
< TabBar
renderLabel = { ( { route , focused , color } ) => (
< Text style = { { color , margin : 8 } } >
{ route . title }
</ Text >
) }
. . .
/ > renderTabBarItem使用TabBarItemProps對象並返回自定義React元素以用作選項卡按鈕的函數。
renderIndicator函數將對象帶有當前路由並返回自定義反應元素,以用作選項卡指示器。
renderBadge函數將對象帶有當前路由並返回自定義反應元素以用作徽章。
onTabPress函數可以在選項卡上執行。它接收到“按下”選項卡的場景,對於滾動到頂部之類的東西很有用。
默認情況下,TAB PRESS還切換“選項卡”。為了防止這種行為,您可以致電preventDefault :
< TabBar
onTabPress = { ( { route , preventDefault } ) => {
if ( route . key === 'home' ) {
preventDefault ( ) ;
// Do something else
}
} }
. . .
/ > onTabLongPress函數可以在Tab長按下執行
activeColor在“活動”選項卡中的圖標定制顏色和標籤。
inactiveColor圖標的自定義顏色和標籤在“無活動”選項卡中。
pressColor材料波紋的顏色(僅Android> = 5.0)。
pressOpacity不透明度按下標籤(僅iOS和Android <5.0)。
scrollEnabled布爾值指示是否可以使標籤欄滾動。
如果將scrollEnabled設置為true ,則還應在tabStyle中指定一個width以改進初始渲染。
bounces布爾值指示滾動時的標籤欄是否彈跳。
tabStyle樣式適用於標籤欄中的單個標籤項目。
默認情況下,所有選項卡項目都根據容器的寬度佔據相同的預定寬度。如果您希望他們採用其原始寬度,則可以在tabStyle中指定width: 'auto' 。
indicatorStyle適用於活動指示器的樣式。
indicatorContainerStyle適用於指示器的容器視圖的樣式。
labelStyle適用於標籤項目標籤的樣式。
contentContainerStyle適用於內部容器的樣式。
style適用於標籤欄容器的樣式。
gap定義選項卡之間的間距。
testID測試塔巴爾的ID。可用於滾動測試中的標籤欄
如果要將TAB視圖與React Navigation的導航系統集成在一起,例如希望能夠使用navigation.navigate等導航到選項卡,則可以使用以下官方集成:
請注意,由於反應導航的局限性,React Navigation 4集成無法使用某些功能。例如,可以動態更改渲染選項卡。
每次索引更改時, renderScene函數都會調用。如果您的renderScene功能很昂貴,那麼如果它們不依賴索引,並使用shouldComponentUpdate或React.memo ,這是一個好主意,將每個路線移至單獨的組件,以防止不必要的重新訂閱者。
例如,而不是:
const renderScene = ( { route } ) => {
switch ( route . key ) {
case 'home' :
return (
< View style = { styles . page } >
< Avatar />
< NewsFeed />
</ View >
) ;
default :
return null ;
}
} ;執行以下操作:
const renderScene = ( { route } ) => {
switch ( route . key ) {
case 'home' :
return < HomeComponent /> ;
default :
return null ;
}
} ;如果您使用的是類組件,則<HomeComponent />是PureComponent :
export default class HomeComponent extends React . PureComponent {
render ( ) {
return (
< View style = { styles . page } >
< Avatar />
< NewsFeed />
</ View >
) ;
}
}或者,用React.memo包裝,如果您使用的功能組件:
function HomeComponent ( ) {
return (
< View style = { styles . page } >
< Avatar />
< NewsFeed />
</ View >
) ;
}
export default React . memo ( HomeComponent ) ;我們需要測量容器的寬度,因此需要等待,然後再在屏幕上呈現一些元素。如果您知道初始寬度,則可以將其傳遞給,我們不需要等待測量。在大多數情況下,這只是窗口寬度。
例如,將以下initialLayout傳遞到TabView :
const initialLayout = {
height : 0 ,
width : Dimensions . get ( 'window' ) . width ,
} ;TAB視圖仍將對尺寸的變化做出反應,並進行相應調整以適應諸如方向變化之類的事物。
如果您有很多路線,尤其是圖像,則可以將動畫放在很多方面。相反,您可以渲染有限數量的路線。
例如,以下操作以在每一側僅渲染2條路線:
const renderScene = ( { route } ) => {
if ( Math . abs ( index - routes . indexOf ( route ) ) > 2 ) {
return < View /> ;
}
return < MySceneComponent route = { route } /> ;
} ;將TabView嵌套在垂直ScrollView中,將禁用TabView內部呈現的FlatList組件中的優化。因此,如果可能的話,請避免這樣做。
lazy和renderLazyPlaceholder道具根據需要渲染路線默認情況下禁用lazy選項,以提供更平滑的選項卡切換體驗,但是您可以啟用它並提供佔位符組件,以獲得更好的懶惰加載體驗。僅當lazy能夠通過渲染路線呈現時,才能提高初始負載性能。有關更多詳細信息,請參考道具參考。
在開發過程中,您可以運行示例應用程序來測試更改。
確保您的代碼通過打字稿和ESLINT。運行以下驗證:
yarn typescript
yarn lint要解決格式錯誤,請運行以下內容:
yarn lint -- --fix請記住,如果可能的話,為您的更改添加測試。