Skip to content

tianyanqiu/NavigatorDemo

Repository files navigation

react-navigation 导航系统的使用

react-navigation的安装

npm install --save react-navigation

yarn add react-navigation

react-navigation的使用

StatusBar

这是控制应用状态栏的控件,我们可以通过hidden属性来控制是否显示状态栏,同时也可以通过barStyle来设置状态栏文本的颜色(目前只支持'default'、'light-content'、'dark-content'),另外我们可以设置backgroundColor属性来改变状态栏的背景色(但此属性只在安卓设备上有效)。例如:

<StatusBar backgroundColor="blue" barStyle="dark-content" /> 

StackNavigator 导航栏

StackNavigator就是屏幕上方的导航栏,提供了屏幕之间的转换的方式。

例如:

export default function HomePage(props) {
    const {navigate} = props.navigation;
        return (
      <View>
        <Text>Hello, Navigation!</Text>
        <Button
          onPress={() => navigate('Chat')}  //点击按钮导航到ChatPage
          title="Chat with Lucy"
        />
      </View>
    );
}

HomePage.navigationOptions = {
    title: 'HomePage'
}
export default function ChatPage(props) {
    const {navigate} = props.navigation;
        return (
      <View>
        <Text>Chat with Lucy!</Text>
        <Button
          onPress={() => navigate.goBack()}  //点击按钮时回调goBack方法返回上一个页面
          title="return HomePage"
        />
      </View>
    );
}
        
const App = StackNavigator({
  Home: { screen: HomePage },
  Chat: { screen: ChatPage }
});

对于StackNavigator我们可以通过navigationOptionsheaderStyle属性自定义其样式,包括背景色,高度等;通过headerTintColor自定义导航栏的颜色,包括图标和标题; 另外还可以通过headerBackTitleStyleheaderTitleStyle分别自定义左侧返回键文字和导航栏标题颜色; 通过title属性自定义导航栏的标题,另外需要注意的是headerBackTitle属性是对下一个场景起作用,拿上面的例子来说,如果我们希望ChatPage的返回键标题为返回,则需要给HomePage设置headerBackTitle属性。

例如:

ChatPage.navigationOptions = {
  title: 'Chat with John',
  headerStyle: {
      backgroundColor: 'red',
    },
    headerTintColor: 'blue',  //自定义导航栏颜色
    headerBackTitleStyle: {  // 自定义左侧返回键文本的颜色
      color: 'white'
    },
    headerTitleStyle: {  //自定义标题的颜色
      color: 'white'
    }
}

显示结果如下:

header

除了上述提到的属性,我们可以通过headerLeftheaderRight分别添加导航栏左、右两侧添加内容,可以是按钮,图标等。下面的代码是在导航栏右侧添加一个按钮:

ChatPage.navigationOptions = {
  title: 'Chat with John',
  headerRight: (
      <Button title='Info' />
    ),
}

显示结果如下:

rightButton

如何将一个新页面加入导航系统?

为了方便导航系统的管理,我们可以在项目中添加一个App.js文件,然后将页面组件引入到App.js文件中,然后通过下面的方式将其加入导航系统:

import { StackNavigator } from 'react-navigation';
import HomePage from './homePage/HomePage';
import ChatPage from './chatPage/ChatPage';
import DetailPage from './detailPage/DetailPage';

export default App = StackNavigator({
  Home: { screen: HomePage},
  Chat: { screen: ChatPage},
  Detail: {screen: DetailPage}
});

Deep Linking

设想我们现在想要使用类似mychat://chat/John的URL来打开我们的App,并直接进入到John的ChatPage,我们需要进行以下几项配置:

  • 首先,我们需要将HomePageChatPageApp.js进行重构

    HomePage.js

    import React, {Component} from 'react';
    import {View, Text, Button} from 'react-native';
    
    export default function HomePage(props) {
        const {navigate} = props.navigation;
            return (
          <View>
            <Text>Hello, Navigation!</Text>
            <Button
              onPress={() => navigate("Chat", { user: "John" })}
              title="Chat with people"
            />
          </View>
        );
    }
    
    HomePage.navigationOptions = {
        title: 'HomePage',
    }

    ChatPage.js

    import React, { Component } from "react";
    import { View, Text, Button, StatusBar } from "react-native";
    
    export default function ChatPage(props) {
      const { params } = props.navigation.state;
      return (
        <View>
          <StatusBar backgroundColor="blue" barStyle="dark-content" />
          <Text>Chat with {params.user}</Text>
          <Button onPress={() => props.navigation.navigate('Detail')} title="进入详情页"></Button>
        </View>
      );
    }
    ChatPage.navigationOptions = ({ navigation }) => {
      const { state, setParams } = navigation;
      const isInfo = state.params.mode === "info";
      const { user } = state.params;
      return {
        title: isInfo ? `${user}'s Contact Info` : `Chat with ${user}`,
        headerRight: (
          <Button
            title={isInfo ? "Done" : `${user}'s Info`}
            onPress={() => setParams({ mode: isInfo ? "none" : "info" })}
          />
        ),
      };
    };

    App.js

    import { StackNavigator } from "react-navigation";
    import HomePage from "./homePage/HomePage";
    import ChatPage from "./chatPage/ChatPage";
    import DetailPage from "./detailPage/DetailPage";
    
    export default (App = StackNavigator({
      Home: { screen: HomePage },
      Chat: { screen: ChatPage, path: "chat/:user" }, //path告诉router需要匹配的path和需要提取的参数
      Detail: { screen: DetailPage }
    }));
  • 设置URL前缀

    App.js

    import React from 'react';
    import {Platform} from 'react-native';
    import { StackNavigator } from "react-navigation";
    import HomePage from "./homePage/HomePage";
    import ChatPage from "./chatPage/ChatPage";
    import DetailPage from "./detailPage/DetailPage";
    
    const MainApp = StackNavigator({
      Home: { screen: HomePage },
      Chat: { screen: ChatPage, path: "chat/:user" }, //path告诉router需要匹配的path和需要提取的参数
      Detail: { screen: DetailPage }
    });
    //安卓的URL前缀应包括host
    const prefix = Platform.OS == 'android' ? 'mychat://mychat/' : 'mychat://';
    
    export default App = () => <MainApp uriPrefix={prefix}></MainApp>
  • iOS配置

    • NavigatorDemo/ios/NavigatorDemo/AppleDelegate.m中添加以下内容

      //添加在文件顶部
      #import <React/RCTLinkingManager.h>
      
      //添加在@end上方
      - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
        sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
      {
        return [RCTLinkingManager application:application openURL:url
                            sourceApplication:sourceApplication annotation:annotation];
      }
    • 在Xcode里,打开项目的NavigatorDemo/ios/NavigatorDemo.xcodeproj.在边栏中选择项目导航到info tab.向下滑动到“URL Types”并且添加一个.在新的URL type,设定名称和url图标对应想导航到的url图标.如下图:

      xcode

    • 重新运行App

      react-native run-ios
    • 打开Safari浏览器,输入mychat://chat/John可以直接打开App,并跳转到John的ChatPage

  • Android配置

    为了在Andorid中链接外链,可以在manifest中创建一个新的intent. 在NavigatorDemo/android/app/src/main/AndroidManifest.xmlMainActivity内添加新的VIEWtypeintent-filter.

     <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="mychat"
              android:host="mychat" />
    </intent-filter>
    

    现在,重新运行:

     react-native run-android
    

    在Android中测试intent操作,运行

     adb shell am start -W -a android.intent.action.VIEW -d "mychat://mychat/chat/John" com.navigatordemo
    

如何在App级别定义导航栏的默认样式?

App.js

import React from "react";
import { Platform, View, StatusBar } from "react-native";
import { StackNavigator } from "react-navigation";
import HomePage from "./homePage/HomePage";
import ChatPage from "./chatPage/ChatPage";
import DetailPage from "./detailPage/DetailPage";

const MainApp = StackNavigator(
  {
    Home: { screen: HomePage },
    Chat: { screen: ChatPage, path: "chat/:user" }, //path告诉router需要匹配的path和需要提取的参数
    Detail: { screen: DetailPage }
  },
  {
    initialRouteName: "Home",
    headerMode: "screen",
    navigationOptions: {
      headerStyle: {
        backgroundColor: "#387ef5"
      },
      headerBackTitle: "返回",
      headerTintColor: "#fff"
    },
  }
);
//安卓的URL前缀应包括host
const prefix = Platform.OS == "android" ? "mychat://mychat/" : "mychat://";

export default App = () => <MainApp uriPrefix={prefix} ></MainApp>;

如何在App级别自定义状态栏?

在导航系统的根页面,也就是demo中的HomePage中定义:

<View>
      <StatusBar backgroundColor="#387ef5" barStyle="light-content" />
      <Text>Hello, Navigation!</Text>
      <Button
        onPress={() => navigate("Chat", { user: "John" })}
        title="Chat with people"
      />
    </View>

参考资料

文档中完整demo地址NavigatorDemo

About

react-navigation导航的使用

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published