React Native导航库react-navigation使用详解

Viewed 0

在上一节中,我们使用了系统提供的导航组件进行页面跳转,但其实用性有限。本文将详细介绍一个功能强大的第三方导航库:react-navigation。首先,我们回顾一下React Native中常见的导航控件。

导航控件

常见的导航主要分为三种:

  1. StackNavigator:类似于普通的导航器,在屏幕上方显示导航栏,用于管理页面堆栈。
  2. TabNavigator:相当于iOS中的TabBarController,在屏幕底部显示标签栏,用于切换不同模块。
  3. DrawerNavigator:实现抽屉效果,可以从屏幕侧边滑出菜单。

在使用navigation的每个界面,navigation都提供了一系列属性和方法。常见的有:

  • navigate:用于跳转到另一个页面。主要参数包括:
    • routeName:目标路由名称,需在app router中注册。
    • params:传递给目标路由的参数。
    • action:(高级)如果目标界面是navigator,可以运行此sub-action。
  • state:通过this.props.navigation.state访问当前路由状态,包含routeNamekeyparams等。
  • setParams:允许界面动态更改路由中的参数,常用于更新header内容。
  • goBack:返回上一级页面。
  • dispatch:向任何navigation传递其他action。

例如,在HomeScreen组件中使用navigate进行跳转:

class HomeScreen extends React.Component {
  render() {
    const {navigate} = this.props.navigation;

    return (
      <View>
        <Text>This is the home screen of the app</Text>
        <Button
          onPress={() => navigate('Profile', {name: 'Brent'})}
          title="点击我跳转"
        />
      </View>
     )
   }
}

通过NavigationActions.navigate创建导航action并dispatch:

import { NavigationActions } from 'react-navigation'

const navigationAction = NavigationActions.navigate({
  routeName: 'Profile',
  params: {},
  action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})
})
this.props.navigation.dispatch(navigationAction)

Reset方法使用

Reset方法会清除所有导航状态,并用新的路由替代:

import { NavigationActions } from 'react-navigation'

const resetAction = NavigationActions.reset({
  index: 0,
  actions: [
    NavigationActions.navigate({ routeName: 'Profile'})
  ]
})
this.props.navigation.dispatch(resetAction)

SetParams方法使用

为指定路由更新参数,该路由必须已存在:

import { NavigationActions } from 'react-navigation'

const setParamsAction = NavigationActions.setParams({
  params: {},
  key: 'screen-123',
})
this.props.navigation.dispatch(setParamsAction)

StackNavigator使用

StackNavigator使用简单,下面是一个常见示例:

class MyHomeScreen extends React.Component {
  static navigationOptions = {
     title: 'Home',
  }

  render() {
    return (
      <Button
        onPress={() => this.props.navigation.navigate('Profile', {name: 'Lucy'})}
        title="Go to Lucy's profile"
      />
    );
  }
}

const ModalStack = StackNavigator({
  Home: {
    screen: MyHomeScreen,
  },
  Profile: {
    path: 'people/:name',
    screen: MyProfileScreen,
  },
});

StackNavigatorConfig配置

StackNavigator的配置选项包括路由选项和视觉选项:

  • 路由选项
    • initialRouteName:设置默认界面,需与route configs中的key匹配。
    • initialRouteParams:初始路由的参数。
    • navigationOptions:屏幕导航的默认选项。
    • paths:路由路径设置的映射。
  • 视觉选项
    • mode:定义渲染和转换模式,可选card(标准iOS/Android切换)或modal(仅iOS,模态视图)。
    • headerMode:指定header渲染方式,可选float(共用header,有渐变效果)、screen(各自header,无渐变)或none(无header)。
    • cardStyle:继承或重载stack中card的样式。
    • onTransitionStartonTransitionEnd:换场动画开始和结束时的回调函数。

可以在组件中定义静态的navigationOptions来定制导航栏:

class ProfileScreen extends React.Component {
  static navigationOptions = {
    title: ({ state }) => `${state.params.name}'s Profile!`,
    header: ({ state, setParams }) => ({
      right: (
        <Button
          title={state.params.editing ? 'Done' : 'Edit'}
          onPress={() => setParams({editing: state.params.editing ? false : true})}
        />
      ),
    }),
  };
  // ...
}

常用配置参数:

  • visible:布尔值,控制header是否可见。
  • title:标题,可以是字符串或React节点。
  • backTitle:iOS平台返回按钮的标题,默认为title值。
  • rightleft:在header右侧或左侧显示的React节点,如按钮。
  • style:header的样式。
  • titleStyle:header标题的样式。
  • tintColor:header的前景色。
  • cardStack:配置card stack。

react-navigation使用详解

安装与基本使用

首先,在项目目录下安装react-navigation库:

npm install --save react-navigation

然后,使用StackNavigator管理页面堆栈。以下是一个简单的入口页面示例:

import React from 'react';
import { AppRegistry, Text } from 'react-native';
import { StackNavigator } from 'react-navigation';

class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Welcome',
  };
  render() {
    return <Text>Hello, Navigation!</Text>;
  }
}

const SimpleApp = StackNavigator({
  Home: { screen: HomeScreen },
});

AppRegistry.registerComponent('SimpleApp', () => SimpleApp);

添加一个新页面ChatScreen,并在HomeScreen中通过Button导航到该页面:

class ChatScreen extends React.Component {
  static navigationOptions = {
    title: 'Chat with Lucy',
  };
  render() {
    return (
      <View>
        <Text>Chat with Lucy</Text>
      </View>
    );
  }
}

class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Welcome',
  };
  render() {
    const { navigate } = this.props.navigation;
    return (
      <View>
        <Text>Hello, Chat App!</Text>
        <Button
          onPress={() => navigate('Chat')}
          title="Chat with Lucy"
        />
      </View>
    );
  }
}

const SimpleApp = StackNavigator({
  Home: { screen: HomeScreen },
  Chat: { screen: ChatScreen },
});

参数传递

在页面跳转时,经常需要传递参数。使用react-navigation传递参数非常简单,只需在navigate方法中添加一个JSON对象:

navigate('Chat', { user: 'Lucy' })

在接收页面中,可以通过this.props.navigation.state.params获取参数:

class ChatScreen extends React.Component {
  static navigationOptions = {
    title: ({ state }) => `Chat with ${state.params.user}`,
  };
  render() {
    const { params } = this.props.navigation.state;
    return (
      <View>
        <Text>Chat with {params.user}</Text>
      </View>
    );
  }
}

TabNavigator使用

TabNavigator用于实现底部导航效果。以下是一个配置示例:

const Tabs = TabNavigator({
    Home: {
        screen: Home,
        navigationOptions: {
            tabBar: {
                label: '首页',
                icon: ({tintColor}) => (<Image source={require('./app/images/home.png')} style={[{tintColor: tintColor},styles.icon]}/>),
            },
        }
    },
    Bill: {
        screen: Bill,
        navigationOptions: {
            tabBar: {
                label: '账单',
               icon: ({tintColor}) => (<Image source={require('./app/images/bill.png')} style={[{tintColor: tintColor},styles.icon]}/>),
            },
        }
    },
    Me: {
        screen: Me,
        navigationOptions: {
            tabBar: {
                label: '我',
                icon: ({tintColor}) => (<Image source={require('./app/images/me.png')} style={[{tintColor: tintColor},styles.icon]}/>),
            },
        }
    }
  }, {
      animationEnabled: false,
      tabBarPosition: 'bottom',
      swipeEnabled: false,
      backBehavior: 'none',
      tabBarOptions: {
          activeTintColor: '#ff8500',
          inactiveTintColor: '#999',
          showIcon: true,
          indicatorStyle: { height: 0 },
          style: { backgroundColor: '#fff' },
          labelStyle: { fontSize: 10 },
      },
});

DrawerNavigator使用

DrawerNavigator实现抽屉侧滑效果。配置示例如下:

const DrawerNav = DrawerNavigator({
    Home: { screen: Home },
    Bill: { screen: Bill },
    Me: { screen: Me },
}, {
    drawerWidth: 200,
    drawerPosition: 'left',
    contentOptions: {
      activeTintColor: 'white',
      activeBackgroundColor: '#ff8500',
      inactiveTintColor: '#666',
      inactiveBackgroundColor: '#fff',
    }
});

iOS版设置注意事项

在iOS中使用react-navigation时,需进行以下设置:

  1. 在Xcode中配置Schemes。
  2. 在AppDelegate.m中添加代码处理深层链接:
    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
      sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
      return [RCTLinkingManager application:application openURL:url
                          sourceApplication:sourceApplication annotation:annotation];
    }
    
  3. 在js组件注册路由时设置唯一路径,例如Home2: { screen: Home2, path:’app/Home2’ }
  4. 通过URL如demo4://app/Home2可以打开应用并跳转到对应页面。

react-native-tab-navigator简介

除了react-navigation,还有一个常用的库react-native-tab-navigator,可用于实现标签导航。以下是一个基本示例代码结构:

import React, { Component } from 'react';
import TabNavigator from 'react-native-tab-navigator';
import { AppRegistry, StyleSheet, Text, Image, View } from 'react-native';

const TabNavigatorItem = TabNavigator.Item;
// 定义图标路径
const TAB_HOME_NORMAL = require('./image/tabbar_homepage.png');
const TAB_MINE_NORMAL = require('./image/tabbar_mine.png');
const TAB_HOME_PRESS = require('./image/tabbar_homepage_selected.png');
const TAB_MINE_PRESS = require('./image/tabbar_mine_selected.png');

export default class HelloWord extends Component {
  constructor(){
    super();
    this.state={
      selectedTab:'Home',
    }
  }

  onPress(tabName){
   if(tabName){
     this.setState({
         selectedTab:tabName,
       }
     );
   }
 }

 renderTabView(title, tabName, tabContent, isBadge){
    var tabNomal, tabPress;
    switch (tabName) {
      case 'Home':
        tabNomal = TAB_HOME_NORMAL;
        tabPress = TAB_HOME_PRESS;
        break;
      case 'Mine':
        tabNomal = TAB_MINE_NORMAL;
        tabPress = TAB_MINE_PRESS;
        break;
      default:
    }
    return(
     <TabNavigatorItem
      selected={this.state.selectedTab === tabName}
      title={title}
      titleStyle={styles.tabText}
      selectedTitleStyle={styles.selectedTabText}
      renderIcon={() => <Image style={styles.icon} source={tabNomal}/>}
      renderSelectedIcon={() => <Image style={styles.icon} source={tabPress}/>}
      onPress={() => this.onPress(tabName)}
      renderBadge={() => isBadge ? <View style={styles.badgeView}><Text style={styles.badgeText}>15</Text></View> : null}
      >
     <View style={styles.page}><Text>{tabContent}</Text></View>
     </TabNavigatorItem>
   );
 }

 tabBarView(){
      return (
        <TabNavigator tabBarStyle={styles.tab}>
          {this.renderTabView('首页','Home','首页模块',true)}
          {this.renderTabView('我的','Mine','我的模块',false)}
        </TabNavigator>
      );
    }

  render() {
    var tabView = this.tabBarView();
    return (
      <View style={styles.container}>
             {tabView}
            </View>
    );
  }
}

// 样式定义
const styles = StyleSheet.create({
  container: { flex: 1 },
  tabText: { fontSize: 10, color: 'black' },
  selectedTabText: { fontSize: 10, color: 'green' },
  tab: { height: 52, alignItems:'center', backgroundColor:'#f4f5f6' },
  badgeView: { width:22, height:14, backgroundColor:'#f85959', borderWidth:1, marginLeft:10, marginTop:3, borderColor:'#FFF', alignItems:'center', justifyContent:'center', borderRadius:8 },
  badgeText: { color:'#fff', fontSize:8 },
  icon: { width: 22, height: 22 },
  page: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#FFFFFF' },
});

AppRegistry.registerComponent('HelloWord', () => HelloWord);

本文介绍了React Native中导航的基本概念、react-navigation库的详细使用方法,以及参数传递和常见导航器的配置。通过合理使用这些导航组件,可以高效地构建复杂的移动应用界面。

0 Answers