React-Navigation V2 使用教程 (一) createStackNavigator

前言:

ReactNavigation出现很久了,并且在最近发布了V2版本,有一些功能的优化,和api的变化。原来的文档已经不适用了,所以新写一篇用来记录一下细节的东西。本篇内容是参照官方英文文档完成。

安装

//推荐yarn
yarn add react-navigation
# or with npm
# npm install --save react-navigation

使用

createStackNavigator

Creating a stack navigator

createStackNavigator是一个返回React组件的函数。
它需要一个路由配置对象,以及一个选项对象(我们现在省略了这个)。
因为createStackNavigator函数返回一个React组件,我们可以直接从App.js导出它以用作我们App的根组件

/**
 * Created by 卓原 on 2018/7/4.
 * route.js
 */

import {createStackNavigator} from 'react-navigation';
import HomeScreen from "./page/HomeScreen";
import DetailsScreen from "./page/DetailsScreen";

const RootStack = createStackNavigator({
    Home: {
        screen: HomeScreen
    },
    Details: {
        screen: DetailsScreen
    }
});


export default RootStack;

App.js



export default class App extends React.Component {

//第一种写法
  render() {
    return <RootStack />;
  }

//第二种写法
render() {
        return (
            <View style={{flex: 1}}>
                <RootStack/>
            </View>
        )

    }
}

切换路由 方法:

  • this.props.navigation.navigate('Details') 将新路由推送到堆栈导航器(如果它尚未在堆栈中),否则它将跳转到该屏幕
  • this.props.navigation.push('Details') 继续推送新路由
  • this.props.navigation.popToTop() 返回到堆栈中的第一个屏幕
  • this.props.navigation.goBack() 返回到上层路由
/**
 * Created by 卓原 on 2018/7/4.
 * DetailsScreen
 */

import React from 'react';
import {
    View,
    Text,
    Button,
} from 'react-native';

export default class DetailsScreen extends React.Component {
    render() {
        return (
            <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
                <Text>Details Screen</Text>
                <Button
                    title="Go to Details... again"
                    onPress={() => this.props.navigation.push('Details')}
                />
                <Button
                    title="Go to Home"
                    onPress={() => this.props.navigation.navigate('Home')}
                />
                <Button
                    title="Go back"
                    onPress={() => this.props.navigation.goBack()}
                />
            </View>
        );
    }
}

以我当前的路由页面举例,我从Home,navigate到Deatils,此时我在Details页面,我执行navigate(‘Details’),不会有任何反应,push(‘Details’)便会跳转到一个新的Details页面,此时,执行goback()那么会回到上一个Details。

将参数传递给下一个路由

通过将params放入一个对象作为navigation.navigate函数的第二个参数,params传递:this.props.navigation.navigate('RouteName',{/ * params go here * /})
获取前一个路由传递的参数:this.props.navigation.getParam(paramName,defaultValue)

//Home页面
                <Button
                    title="Go to Details"
                    onPress={() => this.props.navigation.navigate('Details', {name: '卓原'})}
                />
//Details页面
        const name = navigation.getParam('name', '帅哥');
        const age = navigation.getParam('age', 16);

        const prevObj = navigation.state.params;

如上代码所示,我跳到Details页面时传递了个对象,名叫卓原的人,接收的时候,我本身并不知道传来的是什么,但我有一个默认的属性,默认属性是一个16岁的帅哥,我接收到了前面传来的名字,于是我的属性变成了16岁的卓原。

还可以使用this.props.navigation.state.params直接访问params对象。
如果没有提供params,这可能为null,因此通常使用getParam更容易,因为不必处理这种情况。

配置标题栏

设置标题

屏幕组件可以具有名为navigationOptions的静态属性,该属性是对象或返回包含各种配置选项的对象的函数。
我们用于标题的是title,如以下示例所示

export default class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Home',
  };

  /* render function, etc */
}

默认情况下,createStackNavigator使用平台约定,因此在iOS上标题将居中,而在Android上它将是左对齐的

在标题中使用params

为了在标题中使用params,我们需要使navigationOptions成为一个返回配置对象的函数

export default class DetailsScreen extends React.Component {
    static navigationOptions = ({navigation,navigationOptions }) => {
        console.log(navigation)
        return {
            title: navigation.getParam('name', 'A Nested Details Screen'),
        };
    };

  /* render function, etc */
}

使用setParams更新navigationOptions

通常需要从已安装的屏幕组件本身更新活动屏幕的navigationOptions配置。我们可以使用this.props.navigation.setParams 来做到这一点.

                <Button
                    title="Update the title"
                    onPress={() => this.props.navigation.setParams({name: 'Updated!'})}
                />

此时,我们的标题就从卓原变成了 Updated!

调整标题样式

自定义标题样式时,有三个关键属性:headerStyleheaderTintColorheaderTitleStyle

  • headerStyle:将应用于title的View的样式对象。如果在其上设置backgroundColor,那将是标题的颜色。
  • headerTintColor:后退按钮和标题都使用此属性作为其颜色。
  • headerTitleStyle:如果我们要为标题自定义字体Family,font Weight和其他Text style属性,我们可以用它来做
static navigationOptions = {
        title: 'Home',
        headerStyle: {            //标题栏样式
            backgroundColor: 'red',  
        },
        headerTintColor: '#fff',  //标题文字和按钮颜色
        headerTitleStyle: {       //标题文字样式
            fontWeight: 'bold',
           // color:'blue' 如果这里也写了标题文字的颜色,那么会覆盖headerTintColor的颜色,即标题为蓝色
        },
    };

以上代码对应的标题样式
这里写图片描述

跨屏幕共享通用navigationOptions

export default class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Home',
    /* No more header config here! */
  };

  /* render function, etc */
}

------------------------------------------分割线------------------------------------------------

const RootStack = createStackNavigator({
    Home: {
        screen: HomeScreen
    },
    Details: {
        screen: DetailsScreen
    }
}, {
    /* 主屏幕的标题配置现在在这里 */
    navigationOptions: {
        headerStyle: {
            backgroundColor: '#f4511e',
        },
        headerTintColor: '#fff',
        headerTitleStyle: {
            fontWeight: 'bold',
        },
    }
});

现在,任何属于RootStack的屏幕的标题栏都将采用这个navigationOptions。
当然,也可以像之前那样,在页面中配置标题样式,那会覆盖共享的navigationOptions。

用自定义组件替换标题

有时候,您需要更多的控制权,而不仅仅是改变标题的文本和样式 - 例如,您可能想渲染图像来代替标题,或者将标题变为按钮。
在这些情况下,您可以完全覆盖用于标题的组件并提供您自己的组件。

import React from 'react';
import {
    View,
    Text,
    Button,
    Image
} from 'react-native';

export default class LogoTitle extends React.Component {
    render() {
        return (
            <Image
                source={require('../../image/title.png')}
                style={{width: 30, height: 30}}
            />
        );
    }
}

export default class HomeScreen extends React.Component {

    static navigationOptions = {
        // headerTitle instead of title
        headerTitle: <LogoTitle/>,
    };
  /* render function, etc */
}

这样,标题文字就变成了一张图片。

向标题添加按钮

与标题交互的最常用方法是点击标题左侧或右侧的按钮。

    static navigationOptions = {
        // headerTitle instead of title
        headerTitle: <LogoTitle/>,
        headerRight: (
            <Button
                onPress={() => alert('This is a button!')}
                title="Info"
                color="blue"
            />
        ),
    };
自定义后退按钮

createStackNavigator为后退按钮提供特定于平台的默认值。
在iOS上,这包括按钮旁边的标签,当标题适合可用空间时显示上一屏幕的标题,否则显示“Back”。

可以使用headerBackTitleheaderTruncatedBackTitle更改标签行为。
要自定义后退按钮图像,可以使用headerBackImage
tips:
headerBackTitle,headerTruncatedBackTitle必须在原始屏幕中定义,而不是在目标屏幕中定义。

export default class DetailsScreen extends React.Component {

    static navigationOptions = ({navigation, navigationOptions}) => {
        console.log(navigation)
        return {
            title: navigation.getParam('name', 'A Nested Details Screen'),
            headerBackImage: <Image
                source={require('../../image/title.png')}
                style={{width: 30, height: 30}}
            />
        };
    };

    ...
}

createStackNavigator API

API定义
createStackNavigator(RouteConfigs, StackNavigatorConfig);

RouteConfigs

route configs对象是从路由名称到路由配置的映射,它告诉导航器为该路由提供什么。

createStackNavigator({
  // 对于您可以导航到的每个屏幕,请创建一个这样的新条目:
  Profile: {
    // `ProfileScreen` 是一个React组件,它将成为屏幕的主要内容.
    screen: ProfileScreen,
    // 当StackNavigator加载`ProfileScreen`时,它将被赋予`navigation` prop.

    // 可选: 在Web应用程序中深度链接或使用react-navigation时,将使用以下路径:
       path:'people /:name',
    // 动作和路线参数从路径中提取。

    // 可选: 覆盖屏幕的`navigationOptions`
    navigationOptions: ({ navigation }) => ({
      title: `${navigation.state.params.name}'s Profile'`,
    }),
  },

  ...MyOtherRoutes,
});
StackNavigatorConfig
路由器的选项:

initialRouteName - 设置堆栈的默认屏幕。必须匹配路径配置中的一个键。
initialRouteParams - 初始路线的参数
initialRouteKey - 初始路由的可选标识符
navigationOptions - 用于屏幕的默认导航选项
paths - 路径配置中设置的路径的覆盖映射

视觉选项:

mode - 定义渲染和转换的样式:

  • card - 使用标准的iOS和Android屏幕过渡。这是默认值。
  • modal - 使屏幕从底部滑入,这是一种常见的iOS模式。仅适用于iOS,对Android没有影响。

headerMode - 指定标头的呈现方式:

  • float - 渲染单个标题,保持在顶部,并在屏幕更改时设置动画。这是iOS上的常见模式。
  • screen - 每个屏幕都附有一个标题,标题与屏幕一起淡入和淡出。这是Android上的常见模式。
  • none - 不会呈现标题。

headerTransitionPreset- 指定headerMode: float启用时标头应如何从一个屏幕转换到另一个屏幕。

  • fade-in-place - 标题组件交叉淡入淡出而不移动,类似于iOS的Twitter,Instagram和Facebook应用程序。这是默认值。
  • uikit - iOS的默认行为的近似值。

cardStyle - 使用此prop可以覆盖或扩展堆栈中单个卡的默认样式。
transitionConfig- 返回与默认屏幕转换合并的对象的函数(在类型定义中查看TransitionConfig )。提供的函数将传递以下参数:

  • transitionProps - 为新屏幕过渡道具。
  • prevTransitionProps - 转换旧屏幕的道具。
  • isModal - 布尔值,指定屏幕是否为模态。

onTransitionStart - 卡转换动画即将开始时要调用的函数。
onTransitionEnd - 卡过渡动画完成后要调用的函数。

title
可用作后备的字符串headerTitle。此外,将用作tabBarLabel(如果嵌套在TabNavigator中)或drawerLabel(如果嵌套在DrawerNavigator中)的后备。

header
React元素或给定的函数HeaderProps返回React元素,以显示为标题。设置为null隐藏标题。

headerTitle
标题使用的字符串,反应元素或反应组件。默认为场景title。当使用的成分,它接收allowFontScaling,style和children道具。传递标题字符串children。

headerTitleAllowFontScaling
标题标题字体是否应缩放以遵守“文本大小”辅助功能设置。默认为true。

headerBackImage
React Element或Component在标题的后退按钮中显示自定义图像。使用组件时,它在渲染(tintColor,title)时会收到许多道具。默认为带有react-navigation/views/assets/back-icon.png后方图像源的图像组件,后者是平台的默认后退图标图像(iOS上的V形符号和Android上的箭头)。

headerBackTitle
iOS上后退按钮使用的标题字符串,或null禁用标签。默认为上一个场景headerTitle。headerBackTitle必须在原始屏幕中定义,而不是在目标屏幕中定义。例如,当您有转换A到B并且要禁用headerBackTitleon时B:

StackNavigator({
  A: {
    screen: AScreen,
    navigationOptions: () => ({
      title: `A`,
      headerBackTitle: null
    }),
  },
  B: {
    screen: BScreen,
    navigationOptions: () => ({
      title: `B`,
    }),
  }
});

headerTruncatedBackTitle
当按钮headerBackTitle不适合屏幕时,后退按钮使用的标题字符串。”Back”默认。headerTruncatedBackTitle必须在原始屏幕中定义,而不是在目标屏幕中定义。例如,如果您有转换A到B并且想要截断标签B:

StackNavigator({
  A: {
    screen: AScreen,
    navigationOptions: () => ({
      title: `A`,
      headerBackTitle: 'A much too long text for back button from B to A',
      headerTruncatedBackTitle: `to A`
    }),
  },
  B: {
    screen: BScreen,
    navigationOptions: () => ({
      title: `B`,
    }),
  }
});

headerRight
React Element显示在标题的右侧。

headerLeft
React元素或组件显示在标题的左侧。当使用的成分,它接收到一个数道具呈现时(onPress,title,titleStyle和更多-检查Header.js完整的列表)。

headerStyle
标题的样式对象

headerForceInset
允许将forceInset对象传递给标头中使用的内部SafeAreaView。

headerTitleStyle
标题组件的样式对象

headerBackTitleStyle
后标题的样式对象

headerTintColor
标题的色调

headerPressColorAndroid
材质波纹的颜色(Android> = 5.0)

headerTransparent
默认为false。如果true,标题将没有背景,除非您明确地提供headerStyle或headerBackground。

headerBackground
使用它headerTransparent来提供要在标题的背景中呈现的组件。例如,您可以将其用于模糊视图,以创建半透明标题。

gesturesEnabled
是否可以使用手势来关闭此屏幕。在iOS上默认为true,在Android上默认为false。

gestureResponseDistance
用于覆盖从屏幕边缘开始触摸的距离以识别手势的对象。它具有以下属性:

  • horizontal- 数字 - 水平方向的距离。默认为25。
  • vertical- 数字 - 垂直方向的距离。默认为135。

gestureDirection
用于覆盖关闭手势方向的字符串。default用于正常行为或inverted从右向左滑动。

Navigator Props
创建的导航器组件StackNavigator(…)采用以下属性:

screenProps - 将额外选项传递给子屏幕,例如:

·const SomeStack = createStackNavigator({
  // config
});

<SomeStack
  screenProps={/* this prop will get passed to the screen components as this.props.screenProps */}
/>

举例:

const ModalNavigator =createStackNavigator(
  {
    Main: { screen: Main },
    Login: { screen: Login },
  },
  {
    headerMode: 'none',
    mode: 'modal',
    navigationOptions: {
      gesturesEnabled: false,
    },
    transitionConfig: () => ({
      transitionSpec: {
        duration: 300,
        easing: Easing.out(Easing.poly(4)),
        timing: Animated.timing,
      },
      screenInterpolator: sceneProps => {
        const { layout, position, scene } = sceneProps;
        const { index } = scene;

        const height = layout.initHeight;
        const translateY = position.interpolate({
          inputRange: [index - 1, index, index + 1],
          outputRange: [height, 0, 0],
        });

        const opacity = position.interpolate({
          inputRange: [index - 1, index - 0.99, index],
          outputRange: [0, 1, 1],
        });

        return { opacity, transform: [{ translateY }] };
      },
    }),
  }
);

猜你喜欢

转载自blog.csdn.net/u011272795/article/details/80915040
今日推荐