RN路由-React Navigation--Tab navigation

引言

本來(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>
  );
}

Try this example on Snack

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>
  );
}

Try this example on Snack

讓我們對(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, MobXevent 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} />;
}

Try this example on Snack

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>
  );
}

Try this example on Snack

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>
  );
}

Try this example on Snack

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

See the documentation here

總結(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

參考文檔:React Navigation - Tab navigation

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末寻行,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子匾荆,更是在濱河造成了極大的恐慌拌蜘,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牙丽,死亡現(xiàn)場(chǎng)離奇詭異简卧,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)烤芦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門(mén)举娩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人构罗,你說(shuō)我怎么就攤上這事铜涉。” “怎么了绰播?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵骄噪,是天一觀的道長(zhǎng)尚困。 經(jīng)常有香客問(wèn)我蠢箩,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任谬泌,我火速辦了婚禮滔韵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘掌实。我一直安慰自己陪蜻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布贱鼻。 她就那樣靜靜地躺著宴卖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪邻悬。 梳的紋絲不亂的頭發(fā)上症昏,一...
    開(kāi)封第一講書(shū)人閱讀 51,763評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音父丰,去河邊找鬼肝谭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蛾扇,可吹牛的內(nèi)容都是我干的攘烛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼镀首,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼坟漱!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起更哄,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤靖秩,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后竖瘾,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體沟突,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年捕传,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了惠拭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡庸论,死狀恐怖职辅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情聂示,我是刑警寧澤域携,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站鱼喉,受9級(jí)特大地震影響秀鞭,放射性物質(zhì)發(fā)生泄漏趋观。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一锋边、第九天 我趴在偏房一處隱蔽的房頂上張望皱坛。 院中可真熱鬧,春花似錦豆巨、人聲如沸剩辟。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)贩猎。三九已至,卻和暖如春萍膛,著一層夾襖步出監(jiān)牢的瞬間融欧,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工卦羡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留噪馏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓绿饵,卻偏偏與公主長(zhǎng)得像欠肾,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子拟赊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355