More than code
Welcome to the website

React Navigation 指南 4:配置导航头部

React Navigation 指南 1:Hello React Navigation中,我们看到了空的导航头部,现在来看如何配置。

1. 设置头部标题

屏幕组件可以有一个静态属性navigationOptions,可以是一个对象或者返回一个对象的函数,该对象包含了各种配置选项。用做头部标题的选项叫做title,如下所示 :

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

  /* render function, etc */
}

class DetailsScreen extends React.Component {
  static navigationOptions = {
    title: 'Details',
  };

  /* render function, etc */
}

运行代码,效果如图:

createStackNavigator 默认情况下使用平台约定,所以在iOS上,标题将居中,在Android上它将左对齐。

2. 在导航头部中使用参数

想要在标题中使用参数,我们需要将navigationOptions写成返回配置对象的函数形式。很可能你想在navigationOptions中使用this.props,但是别忘了这是组件类的静态方法,this不指向任何组件实例。因此没有属性props可用。然而,将navigationOptions以函数方式定义,React Navigation调用它的时候会向其传递对象{ navigation, navigationOptions, screenProps }这里,我们关注的是navigation,它正是传递给屏幕组件实例的this.props.navigation。你可能还记得我们可以通过navigation.getParamnavigation.state.paramsnavigation获取参数,现在我们使用navigation.state.params这种方式获取一个参数把它用作标题 :

class DetailsScreen extends React.Component {
  static navigationOptions = ({ navigation }) => {
    const { params } = navigation.state;

    return {
      title: params ? params.title : 'A Nested Details Screen',
    }
  };

  /* render function, etc */
}

传递给函数navigationOptions的是带有如下属性的一个对象 :
+ navigation:屏幕的导航属性信息,路由信息在navigation.state里面。
+ navigationOptions:如果未提供新值,将使用默认或先前的选项
+ screenProps:向下传递额外的options给子screen,在导航栈的根部传入。例如,用它可以实现换肤的功能。

3. 使用setParams更新NavigationOptions

在开发中经常需要在已经挂在的屏幕中更新自己的导航配置。例如,更新标题,操作如下:

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

4. 调整头部样式

自定义屏幕样式的三个关键属性:headerStyleheaderTintColor,和headerTitleStyle
+ headerStyle:应用到包裹头部的View容器上的样式对象. 如果你在该属性上设置了backgroundColor,它会变成屏幕头部的背景颜色。
+ headerTintColor:返回按钮和标题文字的颜色. 下面的例子中,我们把该属性设置成白色#fff,相应地,返回按钮和标题文字的颜色就会是白色。
+ headerTitleStyle:如果我们想自定义fontFamilyfontWeightText的样式属性,我们可以用它来做到这一点。(在此属性中设置color同样生效)

class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Home',
    headerStyle: {
      backgroundColor: '#f4511e',
    },
    headerTintColor: '#fff',
    headerTitleStyle: {
      fontWeight: 'bold',
    },
  };

  /* render function, etc */
}

5. 屏幕共享navigationOptions配置

上面的配置只是在HomeScreen的配置,但是通常我们在一个App中的头部样式是相似的。所以,可以将配置信息放在createStackNavigator中。

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

  /* render function, etc */
}

/* other code... */

const RootStack = createStackNavigator(
  {
    Home: HomeScreen,
    Details: DetailsScreen,
  },
  {
    initialRouteName: 'Home',
    /* The header config from HomeScreen is now here */
    navigationOptions: {
      headerStyle: {
        backgroundColor: '#f4511e',
      },
      headerTintColor: '#fff',
      headerTitleStyle: {
        fontWeight: 'bold',
      },
    },
  }
);

现在,属于RouteStack的每个屏幕都会拥有相同的配置。在必要情况下,可以在每个屏幕组件中覆盖这些配置。

6. 覆盖共享的navigationOptions

某个屏幕中自己定义的navigationOptions会和所属StackNavigator定义的navigationOptions合并起来最终生效,并且在屏幕中定义的navigationOptions的优先级高。例如将头部的前景色和背景色对调:

class DetailsScreen extends React.Component {
  static navigationOptions = ({ navigation, navigationOptions }) => {
    const { params } = navigation.state;

    return {
      title: params ? params.otherParam : 'A Nested Details Screen',
      /* These values are used instead of the shared configuration! */
      headerStyle: {
        backgroundColor: navigationOptions.headerTintColor,
      },
      headerTintColor: navigationOptions.headerStyle.backgroundColor,
    };
  };

  /* render function, etc */
}

7. 使用自定义组件替换标题

有时候我们不仅仅是需要改变标题的文字和样式。比如需要在标题中添加一个图标,在这种情况下,需要使用自定义组件来替换默认的标题组件。

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

class HomeScreen extends React.Component {
  static navigationOptions = {
    // headerTitle instead of title
    headerTitle: <LogoTitle />,
  };

  /* render function, etc */
}

这里我们将组件提供给了headerTitle而不是title属性,headerTitle缺省是一个显示titleText的组件。

8. 添加头部右侧按钮

在开发中,通常会遇到的需求是在头部右侧添加一个按钮:

class HomeScreen extends React.Component {
  static navigationOptions = {
    headerTitle: <LogoTitle />,
    headerRight: (
      <Button
        onPress={() => alert('This is a button!')}
        title="Info"
        color="#fff"
      />
    ),
  };
}

同样,headerLeft用来定义回退按钮。

在上面组件静态变量navigationOptions中,this不绑定到组件实例中,所以在这里没有办法调用组件实例级别的setState,而,头部和组件实例交互是非常常见的需求,如何解决?

9. 头部和屏幕组件交互

头部按钮访问屏幕组件实例上的函数最常见的使用模式是通过params。我们使用一个经典的例子‘计数器’来演示这一点:

class HomeScreen extends React.Component {
  static navigationOptions = ({ navigation }) => {
    const params = navigation.state.params || {};

    return {
      headerTitle: <LogoTitle />,
      headerRight: (
        <Button onPress={params.increaseCount} title="+1" color="#fff" />
      ),
    };
  };

  componentWillMount() {
    this.props.navigation.setParams({ increaseCount: this._increaseCount });
  }

  state = {
    count: 0,
  };

  _increaseCount = () => {
    this.setState({ count: this.state.count + 1 });
  };

  /* later in the render function we display the count */
}

React Navigation不能保证你的屏幕组件会在屏幕标题被渲染之前开始挂载,并且由于increaseCountparamcomponentWillMount中设置,所以在navigationOptions中有可能还不可用,这也是为什么我们获取参数的时候加上了||{}官方认为这个API设计不太好,计划会进行改进。

不使用setParams的话,你可以利用一些状态管理库(比如Redux或者MobX)在头部和屏幕之间通信,这种情况下二者之间的通信方式和任何其他两个组件实例之间的通信方式完全一样。

10. 总结

  • 可以通过navigationOptions静态属性在屏幕组件内自定义标题。
  • navigationOptions可以是一个对象或者一个函数。是函数的时候,被调用时它会被提供一个对象参数{ navigation, navigationOptions, screenProps }
  • StackNavigator初始化时可以提供一个navigationOptions共享给该导航器中所有的屏幕。但是每个屏幕中的静态属性navigationOptions优先级更高,可以覆盖该共享配置。
  • navigationOptions中你可以通过属性headerLeftheaderRight设置头部按钮。
  • 通过headerLeft返回按钮可以被全面定制,但是如果你只想变化标题或者图片,可以使用其他的一些navigationOptions属性:headerBackTitle,headerTruncatedBackTitleheaderBackImage
  • navigationOptions属性列表:
    title:标题,如果设置了这个导航栏和标签栏的title就会变成一样的,不推荐使用
    header:可以设置一些导航的属性,如果隐藏顶部导航栏只要将这个属性设置为null
    headerTitle:设置导航栏标题,推荐
    headerBackTitle:设置跳转页面左侧返回箭头后面的文字,默认是上一个页面的标题。可以自定义,也可以设置为null
    headerTruncatedBackTitle:设置当上个页面标题不符合返回箭头后的文字时,默认改成”返回”
    headerRight:设置导航条右侧。可以是按钮或者其他视图控件
    headerLeft:设置导航条左侧。可以是按钮或者其他视图控件
    headerStyle:设置导航条的样式。背景色,宽高等
    headerTitleStyle:设置导航栏文字样式,如果想去掉安卓导航条底部阴影可以添加elevation: 0,iOS下用shadowOpacity: 0。在最新版本的react-navigation中,安卓标题居中可以使用 flex:1, textAlign: ‘center’来实现
    headerBackTitleStyle:设置导航栏‘返回’文字样式
    headerTintColor:设置导航栏颜色
    headerPressColorAndroid:安卓独有的设置颜色纹理,需要安卓版本大于5.0
    gesturesEnabled:是否支持滑动返回手势,iOS默认支持,安卓默认关闭
    gestureResponseDistance:用于覆盖触摸从屏幕边缘开始识别手势的距离的对象,以识别手势

    • horizontal – number – 水平方向的距离 默认为25。
    • vertical – number – 垂直方向的距离 默认为135。

    gestureDirection:设置关闭手势的方向,默认为default从左向右或inverted从右向左

赞(2) 打赏
未经允许不得转载:李帅帅空间 » React Navigation 指南 4:配置导航头部

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

React CLI - 快速创建react项目脚手架工具

官 网GitHub

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏