引言
本來(lái)打算將React Navigation-Guides這一章內(nèi)容集中寫(xiě)在這篇文章內(nèi)的,但由于篇幅太長(zhǎng)取试,閱讀的時(shí)候很費(fèi)勁敞峭,所以這里將Guides這一章的內(nèi)容分篇來(lái)記錄咱士。首先赃磨,我們來(lái)看看Tab navigation筝家!
Tab navigation
移動(dòng)應(yīng)用中最常見(jiàn)的導(dǎo)航樣式可能是基于標(biāo)簽的導(dǎo)航。 它可以是屏幕底部的標(biāo)題邻辉,也可以是標(biāo)題下方的頂部(甚至代替標(biāo)題)溪王。
本指南介紹createBottomTabNavigator。 您也可以使用createMaterialBottomTabNavigator和createMaterialTopTabNavigator將選項(xiàng)卡添加到您的應(yīng)用程序值骇。
在繼續(xù)之前莹菱,請(qǐng)先安裝@ react-navigation / bottom-tabs:
- npm
npm install @react-navigation/bottom-tabs
- yarn
yarn add @react-navigation/bottom-tabs
1 基于標(biāo)簽的導(dǎo)航的最小示例
import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
function HomeScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
);
}
function SettingsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
2 自定義外觀
這類似于自定義stack導(dǎo)航器的方式—初始化tab導(dǎo)航器時(shí)會(huì)設(shè)置一些屬性,而其他屬性則可以在options中按屏幕自定義雷客。
// You can import Ionicons from @expo/vector-icons/Ionicons if you use Expo or
// react-native-vector-icons/Ionicons otherwise.
import Ionicons from 'react-native-vector-icons/Ionicons';
// (...)
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = focused
? 'ios-information-circle'
: 'ios-information-circle-outline';
} else if (route.name === 'Settings') {
iconName = focused ? 'ios-list-box' : 'ios-list';
}
// You can return any component that you like here!
return <Ionicons name={iconName} size={size} color={color} />;
},
})}
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
}}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
讓我們對(duì)此進(jìn)行剖析:
- tabBarIcon是底部標(biāo)簽導(dǎo)航器中受支持的option芒珠。 因此桥狡,我們知道可以在options prop的屏幕組件上使用它搅裙,但在這種情況下,選擇將其放在Tab.Navigator的screenOptions prop中裹芝,以便于集中圖標(biāo)配置部逮,便于使用。
- tabBarIcon是一個(gè)具有焦點(diǎn)狀態(tài)嫂易,顏色和大小參數(shù)的函數(shù)兄朋。 如果您進(jìn)一步瀏覽配置,將會(huì)看到tabBarOptions以及activeTintColor和inactiveTintColor怜械。 這些默認(rèn)值是iOS平臺(tái)默認(rèn)值颅和,但是您可以在此處更改它們傅事。 傳遞到tabBarIcon的顏色是活動(dòng)的還是不活動(dòng)的,具體取決于聚焦?fàn)顟B(tài)(聚焦為活動(dòng))峡扩。 大小是標(biāo)簽欄期望的圖標(biāo)大小蹭越。
- 閱讀 full API reference 參考,以獲取有關(guān)createBottomTabNavigator配置options的更多信息教届。
3 icons上添加badge
有時(shí)我們想在某些圖標(biāo)上添加badge响鹃。 一種常見(jiàn)的方法是使用一個(gè)額外的視圖容器,并以絕對(duì)定位的方式設(shè)置badge元素案训。
function IconWithBadge({ name, badgeCount, color, size }) {
return (
<View style={{ width: 24, height: 24, margin: 5 }}>
<Ionicons name={name} size={size} color={color} />
{badgeCount > 0 && (
<View
style={{
// On React Native < 0.57 overflow outside of parent will not work on Android, see https://git.io/fhLJ8
position: 'absolute',
right: -6,
top: -3,
backgroundColor: 'red',
borderRadius: 6,
width: 12,
height: 12,
justifyContent: 'center',
alignItems: 'center',
}}
>
<Text style={{ color: 'white', fontSize: 10, fontWeight: 'bold' }}>
{badgeCount}
</Text>
</View>
)}
</View>
);
}
從UI角度來(lái)看买置,該組件已準(zhǔn)備就緒,可以使用强霎,但是您仍然需要找到某種方法從其他地方正確傳遞徽章計(jì)數(shù)忿项,例如使用 React Context, Redux, MobX 或 event emitters.
function HomeIconWithBadge(props) {
// You should pass down the badgeCount in some other ways like React Context API, Redux, MobX or event emitters.
return <IconWithBadge {...props} badgeCount={3} />;
}
4 tabs之間跳轉(zhuǎn)
切換tab使用同樣的API - navigation.navigate。
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('Settings')}
/>
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
</View>
);
}
5 每個(gè)tab上的stack導(dǎo)航
通常脆栋,tab上不僅顯示一個(gè)頁(yè)面倦卖,例如,在您的Twitter feed上椿争,您可以點(diǎn)擊一條推文怕膛,將會(huì)跳轉(zhuǎn)到這個(gè)tab里包含的一個(gè)新頁(yè)面。 您可以認(rèn)為這是因?yàn)槊總€(gè)tab中都有單獨(dú)的導(dǎo)航堆棧秦踪,這正是我們?cè)赗eact Navigation中建模的方式褐捻。
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
function DetailsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Details!</Text>
</View>
);
}
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
const HomeStack = createStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={HomeScreen} />
<HomeStack.Screen name="Details" component={DetailsScreen} />
</HomeStack.Navigator>
);
}
const SettingsStack = createStackNavigator();
function SettingsStackScreen() {
return (
<SettingsStack.Navigator>
<SettingsStack.Screen name="Settings" component={SettingsScreen} />
<SettingsStack.Screen name="Details" component={DetailsScreen} />
</SettingsStack.Navigator>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="Settings" component={SettingsStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
6 為什么要用TabNavigator代替TabBarIOS或其他一些組件
嘗試使用獨(dú)立的tab bar組件而不將其集成到您在應(yīng)用程序中使用的導(dǎo)航庫(kù)中是很常見(jiàn)的。在某些情況下椅邓,這很好柠逞!但是,應(yīng)該警告您景馁,這樣做時(shí)可能會(huì)遇到一些令人沮喪的意外問(wèn)題板壮。
例如,React Navigation的標(biāo)簽導(dǎo)航器會(huì)為您處理Android后退按鈕合住,而獨(dú)立組件通常不會(huì)绰精。此外,如果您(作為開(kāi)發(fā)人員)需要為其調(diào)用兩個(gè)不同的API透葛,則執(zhí)行諸如“跳至該選項(xiàng)卡笨使,然后轉(zhuǎn)到此屏幕”之類的操作更加困難。最后僚害,移動(dòng)用戶界面有許多小的設(shè)計(jì)細(xì)節(jié)硫椰,要求某些組件知道其他組件的布局或存在性-例如级野,如果您具有半透明的標(biāo)簽欄叫惊,則內(nèi)容應(yīng)在其下方滾動(dòng),并且滾動(dòng)視圖應(yīng)具有插圖在底部等于標(biāo)簽欄的高度,因此您可以看到所有內(nèi)容潜索。雙擊選項(xiàng)卡欄雄人,應(yīng)使活動(dòng)導(dǎo)航堆棧彈出到堆棧頂部哥放,再次進(jìn)行操作應(yīng)將活動(dòng)滾動(dòng)視圖滾動(dòng)到該堆棧頂部智嚷。盡管并非所有這些行為都可以通過(guò)React Navigation開(kāi)箱即用地實(shí)現(xiàn),但是如果使用獨(dú)立的選項(xiàng)卡視圖組件糠悯,它們將是實(shí)現(xiàn)的帮坚,并且您將不會(huì)獲得任何這些行為。
7 tab導(dǎo)航器包含一個(gè)stack互艾,想在特定屏幕上隱藏tab bar
總結(jié)
這部分內(nèi)容主要講的是tab navigation的使用方法试和,使用這個(gè)組件可以很方便的設(shè)置tab導(dǎo)航的結(jié)構(gòu),也易于擴(kuò)展和維護(hù)纫普,熟悉的朋友應(yīng)該也有同感阅悍!在設(shè)置badge上,需要另外去研究一下昨稼,后續(xù)補(bǔ)充這部分內(nèi)容节视。
喜歡的朋友,麻煩點(diǎn)個(gè)star哦假栓,謝謝啦~
上一章節(jié):RN路由-React Navigation組件5.x-基本原理(中文文檔)
下一章節(jié):RN路由-React Navigation--Drawer navigation