美文网首页
ReactNative系列(六):react-natigatio

ReactNative系列(六):react-natigatio

作者: 猿海一粟 | 来源:发表于2019-08-26 12:06 被阅读0次
    ReactNative.jpg

    ReactNative整理:《ReactNative系列》

    内容目录

    一、前言
    二、思路与架构
    三、导航搭建
    四、结束


    一、前言

     前面两篇分别介绍了react-navigation的基本导航类型属性和单个导航的使用方式及需要注意的典型配置属性。这篇介绍一下导航类型的嵌套使用。
     项目中的导航器基本都是多种导航的相互嵌套来实现的,常见的有StactNavigatorTabNavigator嵌套,或者StackNavigatorDrawerNavigator嵌套。这里我们以Demo为例,聊一下导航器的嵌套使用。

    二、思路与架构

     应用中的导航架构是根据不同需求来搭建的,具体情况需要具体对待,我们可以对导航器架构进行假设。
     一个应用中往往在启动时会有广告页,几秒之后再进入主页,广告页不会二次出现 -- 可以用SwitchNavigator;主页常见的样式是以底部标签的形式来展示 -- TabNavigator,页面间的跳转则需要堆栈导航来实现 -- StackNavigator,侧滑菜单可以酌情使用 -- DrawerNavigator
     嵌套方式:SwitchNavigator为最外层导航,其包含的两个单页面分别为广告页,以及真正处理业务的页面组成的StackNavigator,用TabNavigator作为堆栈导航的默认第一个页面。

    三、导航搭建

    根据思路开始搭建导航框架:
    1、最外层的导航是用SwitchNavigator,其中包含两个页面,一个是广告页面,另外一个是由多个页面构成的StackNavigator

    /**
     * SplashView - 应用广告页面
     * MainContainer - 多个页面组合成的堆栈导航
     */
    const SwitchConstruct = createSwitchNavigator({
      splash: {
        screen: SplashView
      },
      main: {
        screen: MainContainer
      }
    }, {
      initialRouteName: 'splash',
      backBehavior: 'none'
    });
    
    export default ApplicationContainer = createAppContainer(SwitchConstruct);
    

    其中MainContainer就是由以标签导航为默认首页展示的StackNavigator,新创建的页面都可以加到该堆栈导航中。
    需要注意:只有最外层的SwitchNavigator需要通过createAppContainer链接到应用,其余导航因为是以组件的形式嵌套使用,所以不需要。

    2、堆栈导航中的默认第一个页面为TabNavigator。将主页要展示的三个标签页组合成标签导航加到StackNavigator中。

    export default MainContainer = createStackNavigator({
      tab: {
        screen: TabContainer
      },
    }, {
      headerMode: 'none',
    });
    

    MainContainer中的所有页面都是去掉了系统默认的header--headerMode: 'none',建议使用自己封装的顶部Header,更灵活也更方便移植。

    export default TabContainer = createBottomTabNavigator({
      Home: {
        screen: HomeClass,
        navigationOptions: {
          title: '首页',
          tabBarLabel: '首页',
          tabBarIcon: ({ focused, horizontal, tintColor }) => (
            <Image
              source={focused ? tab_home_select : tab_home}
              style={{ width: 20, height: 20 }}
              resizeMode={'contain'}
            />
          )
        }
      },
      List: {
        screen: ListClass,
        navigationOptions: {
          title: '书单',
          tabBarLabel: '书单',
          tabBarIcon: ({ focused, horizontal, tintColor }) => (
            <Image
              source={focused ? tab_list_select : tab_list}
              style={{ width: 20, height: 20 }}
              resizeMode={'contain'}
            />
          )
        }
      },
      Slide: {
        screen: SlideContainer,
        navigationOptions: {
          title: '我的',
          tabBarLabel: '我的',
          tabBarIcon: ({ focused, horizontal, tintColor }) => (
            <Image
              source={focused ? tab_self_select : tab_self}
              style={{ width: 20, height: 20 }}
              resizeMode={'contain'}
            />
          )
        }
      }
    }, {
      lazy: true,
      initialRouteName: 'Home',
      order: ['Home', 'List', 'Slide'],
      tabBarOptions: {
        activeTintColor: '#FF8800',
        inactiveTintColor: '#666666',
        showIcon: true,
        labelStyle: {
          fontSize: 12
        },
        style: {
          backgroundColor: 'white',
          height: 45
        }
      }
    });
    

    3、TabContainer中有一个为侧滑导航,SlideContainer中同样可以包含多个页面。SelfClassInfoClassSettingClass三个页面被DrawerNavigator包裹,侧滑页面的item没有用react-navigation中的DrawerItems,而是自定义的,使用起来更好控制,效果更多变,个人更推荐自定义封装。

    export default SlideContainer = createDrawerNavigator({
      Self: {
        screen: SelfClass
      },
      Information: {
        screen: InfoClass
      },
      Setting: {
        screen: SettingClass
      }
    }, {
      drawerWidth: 300,
      drawerPosition: 'right',
      order: ['Self', 'Information', 'Setting'],
      initialRouteName: 'Self',
      drawerLockMode: 'locked-closed',
      drawerType: 'slide',
      contentComponent: (props) => {
        return (
          <ScrollView style={{flex: 1, margin: 30}}>
            <SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
              <DrawerItemList {...props} />
            </SafeAreaView>
          </ScrollView>
        );
      },
      contentOptions: {
        activeTintColor: '#FF8800',
        inactiveTintColor: '#666666',
      }
    });
    
    class DrawerItemList extends Component {
      constructor(props) {
        super(props);
      }
    
      itemPress(itemName) {
        Alert.alert('提示', itemName, [{text: '确定', onPress: () => {}}])
      }
    
      render() {
        return this.props.items.map((item, index) => {
          let itemName = '';
          if (item.key === 'Self') {
            itemName = '我的';
          } else if (item.key === 'Information') {
            itemName = '个人信息';
          } else {
            itemName = '系统设置';
          }
          return (
            <TouchableOpacity
              key={index}
              style={styles.itemContainer}
              onPress={() => this.itemPress(itemName)}
            >
              <Text style={styles.itemText}>{itemName}</Text>
            </TouchableOpacity>
          );
        });
      }
    }
    

    每个页面的顶部标题栏可以自行封装,通过父组件向子组件传递props的方式来传递所需要的数据。标题左右两侧的按钮也可以通过属性值控制 -- 展示文本或图片。

    /**
     * 标题顶部的左右两侧按键可以通过传递类型来区分
     *  leftType:左侧按钮类型 -- 图片或文字
     *  rightType:右侧按钮类型 -- 图片或文字
     */
    export default class BaseTitle extends Component {
      constructor(props) {
        super(props);
      }
    
      renderLeftView(leftType) {
        if (leftType === 1) {
          return (
            <Image
              style={styles.leftImage}
              source={BackImage}
            />
          );
        }
        return null;
      }
    
      renderRightView(rightType) {
        if (rightType === 1) {
          return (
            <Image
              style={styles.rightImage}
              source={this.props.rightImage}
            />
          );
        }
        return null;
      }
    
      render() {
        const { leftType, rightType, title } = this.props;
        return (
          <View style={styles.constainer}>
            <TouchableOpacity
              style={styles.leftView}
              onPress={() => {
                if (leftType !== 0) {
                  this.props.onLeftPress();
                }
              }}
            >
              {this.renderLeftView(leftType)}
            </TouchableOpacity>
            <View style={styles.titleView}>
              <Text
                style={styles.titleText}
                numberOfLines={1}
              >
                {title}
              </Text>
            </View>
            <TouchableOpacity
              style={styles.rightView}
              onPress={() => {
                if (rightType !== 0) {
                  this.props.onRightPress();
                }
              }}
            >
              {this.renderRightView(rightType)}
            </TouchableOpacity>
          </View>
        );
      }
    }
    

    4、演示效果

    效果图.gif

    四、结束

    SwitchNavigator为最上层导航,包含StackNavigator --> StackNavigator用作主体逻辑页面控制导航,包含TabNavigator --> TabNavigator用作可切换标签的首页导航,包含DrawerNavigator --> DrawerNavigator用作侧滑菜单展示,包含侧滑菜单页面。
     这里更主要的是强调导航的嵌套方式,各类导航的具体属性没有过多展示,实际应用中需要根据需求做出调整。 各个导航器中的路由页面比较简单,没有具体的代码展示。到这里整个react-navigation就介绍完了,希望能帮到大家。
    发现有问题的地方希望大家指出,共同讨论,喜欢的可以点赞关注

    相关文章

      网友评论

          本文标题:ReactNative系列(六):react-natigatio

          本文链接:https://www.haomeiwen.com/subject/pmtykctx.html