react-navigation 5X版本总结

本文总结了React Navigation V5的关键概念,包括NavigationContainer、Navigator、Screen的属性,以及StackNavigator的options对象。重点讲解了如何安装、简单使用,并详细阐述了各个组件的属性和功能,如initialState、screenOptions、自定义页面过渡效果等。
摘要由CSDN通过智能技术生成

react-navigation V5 总结

注: 5x版本不同于4x版本,包括包,以及使用方法都有较大的改变。

安装
yarn add react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view @react-navigation/native

yarn add react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view @react-navigation/native

react-native-gesture-handler            // 用于手势切换页面
react-native-screens                    // 用于原生层释放未展示的页面,改善 app 内存使用
react-native-safe-area-context          // 用于保证页面显示在安全区域(主要针对刘海屏)
@react-native-community/masked-view     // 用在头部导航栏中返回按钮的颜色设置
@react-navigation/native                // 为 React Navigation 的核心

官方文档中提到的 yarn add react-native-reanimated,该依赖在使用 DrawerNavigator 才用的到,不晓得为啥放到了总的安装文档中,或许后期升级可能会用到,尽量也装上。

注意: 安装完之后,在 js 入口文件,如 index.js 顶部添加 import 'react-native-gesture-handler';,少了这一句,可能会导致生产环境 app 出现闪退现象。

在 App.js 中添加以下代码,激活 react-native-screens 的原生端,与4x版本不同,不需要修改其他文件了

import { enableScreens } from 'react-native-screens';
enableScreens();
简单使用
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

const Tab = createBottomTabNavigator();
const Stack = createStackNavigator()

const Main = () => (<Tab.Navigator
    initialRouteName={String}
    [children={Component}]
    screenOptions={}

    backBehavior={true}
    lazy={}
    tabBar={}
    tabBarOptions={}
>
  <Tab.Screen
      name={String}
      options={}
      listeners={}
      component={} || children={}
      initialParams={}
  />
</Tab.Navigator>);


const App = () => (<NavigationContainer
  theme={theme}
  initialState={initialState}
  onStateChange={newState => {} }
  [children={Component}]
  ref={}
  independent={boolean}
>
  <Stack.Navigator
    initialRouteName={String}
    [children={Component}]
    screenOptions={}

    mode={}
    headerMode={}
    keyboardHandlingEnabled={}
  >
    <Stack.Screen 
      name="Main"
      component={Main}
    />
    <Stack.Screen 
      name={String}
      options={}
      listeners={}
      component={} || children={}
      initialParams={}
    />
  </Stack.Navigator>
</NavigationContainer>)
详解
一.NavigationContainer

该组件在 @react-navigation/native 中定义,为顶层容器,一般情况,一个 APP 只有一个(以下是该标签的属性)

0.them

主题,该属性由 @react-navigation/native 缓存,但并未有任何作用,会下发到导航器,由导航器获取并加以利用,默认为以下属性:

theme={
    dark: boolean;
    colors: {
        primary: string;
        background: string;
        card: string;
        text: string;
        border: string;
    };
}
1.initialState

自定义传入变量,多用于 deepLink,该项暂未验证

2.onStateChange

导航状态变化的监听函数,可用于页面统计或其他操作

3.children

子组件(导航器 Navigator 组件),该项一般使用 jsx 直接插入,而不是通过 props 传递,比如上面的示例,childrenStack.Navigator

4.ref

获取 NavigationContainer 实例,用于调用实例 api,可通过 console.log 打印可用 api

5.independent

此导航容器是否应独立于父容器,如果未将其设置为“ true”,则此容器不能嵌套在另一个容器中,并且会断开所有子级导航器与父容器的连接。
该项并未在官方文档中发现,但源码中可以看到,不建议使用,一般情况也很少有多个顶级容器。

二.Navigator

导航器的根组件,用于包裹导航器下的页面;通过阅读源码可以知道所有导航器都支持:

1. initialRouteName

导航器默认要显示的 screen

2. children

导航器包裹的 screens,通常不会使用 Props 传递,而是在 jsx 中实现。

3. screenOptions

参看以上伪代码,导航器包裹的 screen 属性是一样的,都有一个 options 属性,而 screenOptionsoptions 的值是完全相同的,作为 options 的默认值。

阅读 @react-navigation/core 源码,这个参数的值可以是 ObjectFunction({route, navigation}) 返回 Object,且未对 Object 字段做任何限制,而只是为导航器的实现提供了一个顶层 API

screenOptions = {
    title, header, headerShown, ........
}

// 或通过函数返回
screenOptions = { ({route, navigation}) => {
    return {
      title, header, headerShown, ........
    }
}}
// 以上为基础属性,适用于所有导航器,不同的导航器会在此基础中拓展额外的属性

@react-navigation/stack   // 拓展了 mode / headerMode / keyboardHandlingEnabled 属性 
@react-navigation/bottom-tabs  // 继承 @react-navigation/routers 的拓展属性 backBehavior  拓展了 lazy / tabBar / tabBarOptions 属性
三.Screen

导航器内的具体页面,该组件是在 @react-navigation/core 中实现的,与导航器无关,所有导航器的 screen 都支持且仅支持以下属性

1.name

页面名称,可用于导航跳转

2.options

Stack.Navigator 中的 screenOptions 相同,单独设置来覆盖 screenOptions 的配置;同样的,可以设置为 ObjectFunction;具体结构由 Screen 所属的 Navigator 类型决定。

3.listeners

监听 screen 事件,具体会收到什么回调由所属的 Navigator 类型决定,如 @react-navigation/stackevents@react-navigation/bottom-tabsevents;该属性的值与 options 有点类似,可以指定为 ObjectFunction,如

listeners={{
    tabPress: e => {
      // Prevent default action
      e.preventDefault();
    },
}}

// 或通过函数返回
listeners={({ navigation, route }) => {
    return {
        tabPress: e => {
          // Prevent default action
          e.preventDefault();
        },
    }
}}
3.component / children

Screen 绑定的组件, 可通过 component 指定组件对象,或直接使用 children 定义组件;二者互斥,一般使用 component 属性来定义

4.initialParams

传递给 Screen 组件的初始化 params

4.StackNavigator options 对象中属性

标题

  • title: string, 标题文字
  • headerTitleAlign: 标题对齐方式,支持 left (Android 默认) / center (iOS 默认)
  • headerTitleAllowFontScaling: 标题文字是否随系统文字大小缩放
  • headerTintColor: 标题颜色
  • headerTitleStyle: 自定义标题文字样式
  • headerTitleContainerStyle: 自定义标题文字所在 View 容器的样式
  • headerTitle: 标题,可直接设置文字,优先级高于 title;也可以设置为函数,返回一个组件,函数参数为 {allowFontScaling, style, children},这三个参数是由上面属性结合而来。

左侧返回组件

  • headerBackImage: 返回键,设置为一个函数,返回“返回键”组件,函数参数为 {tintColor:"标题颜色"}
  • headerBackTitle: string 返回键右侧的返回文字
  • headerTruncatedBackTitle: 返回文字过长,标题栏无法显示时的替代返回文字,默认: “Back”
  • headerBackAllowFontScaling: 返回文字是否随系统文字大小缩放
  • headerBackTitleStyle: 自定义返回文字样式
  • headerBackTitleVisible: 是否显示返回文字,Android 默认 false,iOS 默认 true
  • headerPressColorAndroid: Android 5 以上,点击返回按钮的水波纹颜色
  • headerLeftContainerStyle: 自定义返回键和返回文字所在容器的样式
  • headerLeft: 自定义 HeaderBackButton 左侧组件,指定为函数 或 RN组件,props 会传递上面的返回键和返回文字相关的设置

右侧自定义组件

  • headerRight: 自定义标题栏右侧组件
  • headerRightContainerStyle: 自定义右侧组件所在容器的样式

标题栏整体属性

  • headerStatusBarHeight: 设置 statusBar 高度,Header 组件会 paddingTop 这个值以保证在刘海屏机型也可以正常使用,默认会由系统自动获取。
  • headerStyle: 自定义标题栏样式
  • headerTransparent: 标题栏是否透明,与在 headerStyle 直接设置 backgroundColor 的不同在于:这里设置透明,会使页面的 marginTop 为 0,此时需要定义 headerBackground 组件来遮挡。
  • headerBackground: 标题栏背景组件,配合 headerTransparent 使用的,可以用来实现毛玻璃 Header 效果。
  • safeAreaInsets: Header安全区域设置(针对刘海屏机型),默认情况下会自动设置,但也可以使用 {left, right, top, bottom} 手动设置,自定义设置注意考虑横竖屏的情况。
  • headerShown: 是否显示标题栏
  • header: 自定义标题栏组件,定义为函数,返回一个 RN 组件;设置该属性,即不使用默认 Header 了,以上属性失效。
option中与页面相关属性
  • cardStyle: 页面 Card 的样式

  • cardShadowEnabled: 是否显示 Card 边缘的阴影组件;该组件是一个宽度为 3、紧贴边缘、使用 style.shadowOffset 定义阴影的 view 组件,所以该组件目前不支持 android,默认也仅在 iOS 上开启。

  • cardOverlayEnabled: 是否在 Card 下方添加一个组件(也就是在前一个 Card 的上方添加一个组件)

  • cardOverlay: 函数,返回 cardOverlayEnabled=true 要覆盖的组件,该组件可用于页面切换时的效果设定,比如一个黑色的 view,切换过程中逐渐透明,甚至是毛玻璃组件,下方页面就呈现出一种逐渐显示的感官。

与页面切换效果相关的属性
  • animationEnabled: 是否使用页面切换动效,该属性在 web 端为关闭状态
  • animationTypeForReplace: 动画切换过程使用的类型: “push” 或 “pop”
  • cardStyleInterpolator: 页面过渡的动画效果配置;配置动画函数,时长等。
  • cardStyleInterpolator: 函数,返回页面过渡过程中 Card 内相关组件的插值样式。
  • headerStyleInterpolator: 函数,返回页面过渡过程中 Header 内相关组件的插值样式。
与页面切换手势相关的属性
  • gestureEnabled: 是否支持手势返回,iOS默认开启(不开启的话只能在页面上自定义返回按钮了),Android 默认是关闭的(Android 除了返回按钮,还有物理/虚拟返回键)
  • gestureDirection: 返回的手势滑动方向,支持以下值
    • horizontal: 从左到右
    • horizontal-inverted: 从右到左
    • vertical: 从上到下
    • vertical-inverted: 从下到上
  • gestureResponseDistance: 从边缘为起点,支持手势返回的距离,格式为 {horizontal:25, vertical:135};比如手势方向 gestureDirectionhorizontal,那么只有在左边缘 25 以内的区域向右滑动才会响应。
  • gestureVelocityImpact: 触摸返回的手速设置,在手速低于该值时,滑动距离需大于滑动方向上尺寸的 50% 才会返回到上一页,否则弹回;高于所设置手速,即使滑动距离未达到50%,也会返回到上一页面;默认值为 0.3
切换效果

由以上属性可以看出,页面过渡效果由以下属性共同构成:

  • transitionSpec

  • cardStyleInterpolator

  • headerStyleInterpolator

  • 可通过这三个属性实现不同的过渡效果;另外若 gestureEnabled=true,意味着不同过渡效果也要设置相匹配的 gestureDirection; 所以可以将这四个属性配置为一组,方便直接调用,如:

    const transition = {
         gestureDirection:"horizontal",
         transitionSpec: {},
         cardStyleInterpolator:() => {},
         headerStyleInterpolator:() => {},
    }
    <Stack.Navigator
        screenOptions={
           cardStyle:{},
           gestureEnabled:true,
           ...transition
        }
    >
        <Stack.Screen />
    </Stack.Navigator>
    

    React Navigation 的设计初衷应该也在于此,所以其默认提供了几组属性,可以直接使用。

  • SlideFromRightIOS: 仿原生 iOS 左右滑动的过渡效果

  • ModalSlideFromBottomIOS: 仿原生 iOS Modal 上下滑动的过渡效果

  • ModalPresentationIOS: 仿原生 iOS 13 Modal 卡片的上下滑动过渡效果,ModalSlideFromBottomIOS 为下方页面不动,新页面从底部滑出至顶部;而 ModalPresentationIOS,下方页面会有小幅缩小,新页面弹出后,最顶端会保留一段距离,感官上如同弹出一个卡片,知乎的查看评论就是这个效果;该效果在 android 上目前无法完美使用,因为 react-native-screens 会回收旧页面,所以下方页面被回收,导致弹出卡片底部为空白,除非不通过 enableScreens() 启用回收特性,但这又影响了性能。

  • FadeFromBottomAndroid: 仿原生 Android Oreo 上下滑动的过渡效果,新页面从底部滑出,由半透明逐渐不透明。

  • RevealFromBottomAndroid: 仿原生 Android Pie 上下滑动的过渡效果,新页面从底部逐渐展开。

  • DefaultTransition: 当前的默认过渡效果,android 根据系统版本为 FadeFromBottomAndroidRevealFromBottomAndroid,iOS 为 SlideFromRightIOS

  • ModalTransition: 在 Stack.Navigator.mode="modal" 时的默认过渡效果,android 同上, iOS 为 ModalSlideFromBottomIOS

使用方法:

import { TransitionPresets  } from '@react-navigation/stack';

<Stack.Navigator
    screenOptions={
       cardStyle:{},
       gestureEnabled:true,
       ...TransitionPresets.SlideFromRightIOS,
    }
>
    <Stack.Screen />
</Stack.Navigator>

自定义切换效果

1.transitionSpec
const config = {
  animation: 'timing || spring',
  config: {

    // animation="timing" 支持:
    duration:1000,
    easing: Easing.ease,
   
    // animation="spring" 支持:
    stiffness: 1000,
    damping: 500,
    mass: 3,
    overshootClamping: true,
    restDisplacementThreshold: 0.01,
    restSpeedThreshold: 0.01,

  },
};

transitionSpec = {
    open: config,   // 新页面弹出时动效
    close: config,   // 新页面收回时动效,一般二者为同一个
};


// React Navigation 提供了几个默认的,可直接使用或作为参考
import { TransitionSpecs } from '@react-navigation/stack';
transitionSpec = TransitionSpecs.TransitionIOSSpec 
transitionSpec = TransitionSpecs.FadeInFromBottomAndroidSpec 
transitionSpec = TransitionSpecs.FadeOutToBottomAndroidSpec 
transitionSpec = TransitionSpecs.RevealFromBottomAndroidSpec 
2.cardStyleInterpolator

通过函数返回以下样式

  • containerStyle: Card 所在 Animated.View 容器的样式
  • cardStyle: Card 样式
  • overlayStyle: 在 cardOverlayEnabled=true 时,自定义 cardOverlay 组件的样式
  • shadowStyle: 在 cardShadowEnabled=true 时,Card 边缘的阴影组件样式
cardStyleInterpolator = () => {
    return  {
          containerStyle:{},
          cardStyle:{},
          overlayStyle:{},
    }
}

// React Navigation 提供了几个默认的,可直接使用或作为参考
import { CardStyleInterpolators } from '@react-navigation/stack';
cardStyleInterpolator = CardStyleInterpolators.forHorizontalIOS
cardStyleInterpolator = CardStyleInterpolators.forVerticalIOS 
cardStyleInterpolator = CardStyleInterpolators.forModalPresentationIOS 
cardStyleInterpolator = CardStyleInterpolators.forFadeFromBottomAndroid 
cardStyleInterpolator = CardStyleInterpolators.forRevealFromBottomAndroid 
HeaderStyleInterpolators

通过函数返回以下样式

  • backgroundStyle: Header 背景组件的样式
  • leftButtonStyle: Header 左侧返回键所在 Animated.View 容器的样式
  • leftLabelStyle: Header 返回键旁边的返回文字所在 Animated.Text 的样式
  • titleStyle: Header 标题所在 Animated.View 容器的样式
  • rightButtonStyle: Header 右侧 Animated.View 容器的样式
HeaderStyleInterpolators = () => {
    return  {
          leftButtonStyle:{},
          leftLabelStyle:{},
          titleStyle:{},
    }
}

// React Navigation 提供了几个默认的,可直接使用或作为参考
import { HeaderStyleInterpolators } from '@react-navigation/stack';
HeaderStyleInterpolators = HeaderStyleInterpolators.forUIKit 
HeaderStyleInterpolators = HeaderStyleInterpolators.forFade 
HeaderStyleInterpolators = HeaderStyleInterpolators.forStatic 

以上三个属性可全部自定义,也可以部分自定义,部分使用 React Navigation 提供的预置,最后在添加一个 gestureDirection 属性就可构成一组自定义页面切换效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值