• React-native Stack 和 TabBottom 和 Drawer的 导航嵌套使用


    说实话 RN 的文档,我表示看的很吃力

    此文章为ReactNavigation导航库5.0版本的第4篇,前几篇系列文章如下:
    React Navigation5.0系列一:StackNavigator的使用
    React Navigation5.0系列二:TabNavigation的使用
    React Navigation5.0系列三:Drawer navigation的使用
    此前几篇系列文章,主要讲了StackNavigator, TavNavigation以及Drawer Navigation的使用讲解,现实中往往是不同的导航组件组合进行使用的,本篇文章主要讲解导航的嵌套使用及注意事项。

    创建需要的页面

    // 设置页面
    const SettingsScreen = ({ navigation }) => {
      return (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
          <Text>SettingScreen</Text>
          <Button
            title="Go to Details"
            onPress={() => navigation.navigate('Detail')}
          />
        </View>
      )
    }
    // 首页
    const HomeScreen = ({ navigation }) => {
      return (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
          <Text>HomeScreen</Text>
          <Button
            title="Go to Details"
            onPress={() => navigation.navigate('Detail')}
          />
        </View>
      )
    }
    // 详情页
    const DetailScreen = ({ navigation }) => {
      return (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
          <Text>DetailScreen</Text>
          <Button
            title="Go to Detail Again"
            // onPress={() => navigation.navigate('Detail')}
            onPress={() => navigation.push('Detail')}
          />
          <Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
          <Button title="Go back" onPress={() => navigation.goBack()} />
          <Button
            title="Go back to first screen in stack"
            onPress={() => navigation.popToTop()}
          />
        </View>
      )
    }

    创建三个对应的导航器实例

    const Tab = createBottomTabNavigator(); // 选项卡页签tab navigator 实例
    const RootStack = createStackNavigator(); // 堆栈stack 实例
    const Drawer = createDrawerNavigator(); //  抽屉drawer实例

    创建底部导航路由,采用系列二文章代码

    function IconWithBadge({ icon, badgeCount, size }) {
      return (
        <View style={{  24, height: 24, margin: 5 }}>
          <Image source={icon} style={{
             size,
            height: size
          }} />
          {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,
                 12,
                height: 12,
                justifyContent: 'center',
                alignItems: 'center',
              }}
            >
              <Text style={{ color: 'white', fontSize: 10, fontWeight: 'bold' }}>
                {badgeCount}
              </Text>
            </View>
          )}
        </View>
      );
    }
    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} />;
    }
    
    const TabScreen = () => {
      return (
        <Tab.Navigator 
        headerMode='none' 
        screenOptions={({ route }) => ({
          tabBarIcon: ({ focused, color, size }) => {
            if (route.name === 'Home') {
              return (
                <HomeIconWithBadge
                  icon={
                    focused
                      ? HomeIconActive
                      : HomeIconNormal
                  }
                  size={size}
                  color={color}
                />
              );
            } else if (route.name === 'Settings') {
              return (
                <Image
                  source={focused ? WorkIconActive : WorkIconNormal}
                  style={{ size, height: size}}
                />
              );
            }
          },
        })}
        tabBarOptions={{
          activeTintColor: 'tomato',
          inactiveTintColor: 'gray',
        }}
        >
          <Tab.Screen name="Home" component={HomeScreen} />
          <Tab.Screen name="Settings" component={SettingsScreen} />
        </Tab.Navigator>
      )
    }

    堆栈(Stack)与Tab嵌套

    const rootRouteScreen = () => {
      return (<RootStack.Navigator initialRouteName={'TabNav'}>
              <RootStack.Screen name='TabNav' component={TabScreen} />
              <RootStack.Screen name="Detail" component={DetailScreen} />
             </RootStack.Navigator>
      )
    }

    Stack Navigator, Tab Navigator与Drawer Navigator综合嵌套

    const App = () => {
      return (
        <NavigationContainer>
          <Drawer.Navigator initialRouteName="Home"
            drawerType='slide'
            drawerContent={(props) => <CustomDrawerContent {...props} />}
          >
            <Drawer.Screen name='root' component={rootRouteScreen} />
            <Drawer.Screen name='Setting' component={SettingsScreen} />
          </Drawer.Navigator>
        </NavigationContainer>
      );
    }

    最后我们来看一下效果

    在这里插入图片描述

    在这里插入图片描述

    嵌套导航的最佳实践

    建议将嵌套做到最少,应该尝试采用尽可能少的嵌套来实现你的业务需求,因为多层嵌套会导致如下几个问题:

    • 在多层嵌套的页面,代码难以维护
    • 深度嵌套的视图层次结构,这可能会导致低端设备的内存和性能问题
    • 嵌套相同类型的导航器(例如,选项卡内的选项卡,抽屉内的抽屉等)让用户的体验极差。
  • 相关阅读:
    python+soket实现UDP协议的客户/服务端中文聊天程序
    如何实现PyQt5与QML响应彼此发送的信号?
    用 eric6 与 PyQt5 实现python的极速GUI编程(系列04)---- PyQt5自带教程:地址簿(address book)
    用 eric6 与 PyQt5 实现python的极速GUI编程(系列03)---- Drawing(绘图)(3)-- 画线
    用 eric6 与 PyQt5 实现python的极速GUI编程(系列03)---- Drawing(绘图)(2)-- 画点
    用 eric6 与 PyQt5 实现python的极速GUI编程(系列03)---- Drawing(绘图)(1)-- 绘写文字
    仿百度壁纸client(六)——完结篇之Gallery画廊实现壁纸预览已经项目细节优化
    软件概要设计说明书—模板
    Android--Handler的用法:在子线程中更新界面
    在PreferenceAcitity中使用Fragement时避免额外的Left和RightPadding
  • 原文地址:https://www.cnblogs.com/yuerdong/p/14041321.html
Copyright © 2020-2023  润新知