React Navigation 基础 5 : 配置导航头部

配置导航头部

设置头部标题

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

// 这是一个屏幕组件
class HomeScreen extends React.Component {
  // 静态对象属性,名称为 navigationOptions
  static navigationOptions = {
    title: 'Home', // 设置头部标题
  };

  /* 这里是 render 函数等 */
}

// 这是另外一个屏幕组件
class DetailsScreen extends React.Component {
  // 静态属性,名称为 navigationOptions
  static navigationOptions = {
    title: 'Details', // 设置头部标题
  };

  /* 这里是 render 函数等 */
}

→ 运行这段代码

StackNavigator缺省采用了平台自己的约定,所以在iOS上标题会居中,而安卓上会左对齐。

标题中使用参数

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

class DetailsScreen extends React.Component {
// 静态函数属性,但是React Navigation在某个该类的组件调用此函数时会传递参数对象 :
// { navigation, navigationOptions, screenProps }
  static navigationOptions = ({ navigation }) => {
    const { params } = navigation.state;
    
    return {
      title: params ? params.otherParam : 'A Nested Details Screen',
    }
  };

  /* 这里是 render 函数等 */
}

→ 运行这段代码

传递给函数navigationOptions的是带有如下属性的一个对象 :

  • navigation - 屏幕的导航属性信息,路由信息在navigation.state里面。
  • screenProps - The props passing from above the navigator component
  • navigationOptions - 如果没有新值被提供时使用的缺省值或者之前使用的值

上面的例子我们只需要navigation,但有些情况下你可能需要screenProps或者navigationOptions

##使用setParams更新navigationOptions
我们经常需要从挂载的屏幕自己内部更新当前活跃屏幕的navigationOptions配置,像这个样子操作:

  /* 在render()里面 */
  <Button
    title="更新头部标题"
    onPress={() => this.props.navigation.setParams({otherParam: 'Updated!'})}
  />
  /**结合上面的例子使用这个例子,上面的例子中,头部标题设置成等于 params.otherParam **/

→ 执行这段代码

调整头部样式

定制屏幕自己的头部样式有三个关键属性: headerStyle,headerTintColorheaderTitleStyle

  • headerStyle: 应用到包裹头部的View容器上的样式对象. 如果你在该属性上设置了backgroundColor,它会变成屏幕头部的背景颜色。
  • headerTintColor:返回按钮和标题文字的颜色. 下面的例子中,我们把该属性设置成白色#fff,相应地,返回按钮和标题文字的颜色就会是白色。
  • headerTitleStyle: if we want to customize the fontFamily, fontWeight and other Text style properties for the title, we can use this to do it.
class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Home',
    headerStyle: {
      backgroundColor: '#f4511e',
    },
    headerTintColor: '#fff',
    headerTitleStyle: {
      fontWeight: 'bold',
    },
  };

  /* render function, etc */
}

→执行这段代码

这里有一些事情需要注意:

  1. iOS上,状态态文本和图标是黑色的,在暗色背景下这看起来可不咋地。这里我们不想讨论这个问题,但很确定的是你可以定制你的状态条来和你的屏幕颜色匹配,状态条指南里面说了方法。
  2. 我们所做的配置仅仅应用到Home屏幕;当我们导航到Details屏幕,缺省的样式又回来了。现在我们来看如何屏幕共享navigationOptions配置。

屏幕共享navigationOptions配置

通常我们需要把许多屏幕的头部配置成很相似。比如,你公司的品牌色是红色,所以你想让头部变成红色背景白色文字。恰巧,这正是我们上面所执行的例子中HomeScreen屏幕头部的配色方案。但是你会注意到,当你跳到DetailsScreen屏幕时,头部配色又回到了缺省配置。将navigationOptions属性配置从HomeScreen复制到DetailsScreen是不是有点可怕?那要是对应用中的每一屏都这么做呢?谢天谢地,我们不需要这么做。我们可以把配置挪到StackNavigator上面来。

class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Home',
    /* 这里,在每个需要相同头部定义的屏幕类的内部,不再定义头部样式 */
  };

  /* render function, etc */
}

/* other code... */

const RootStack = StackNavigator(
  {
    Home: {
      screen: HomeScreen,
    },
    Details: {
      screen: DetailsScreen,
    },
  },
  {
    initialRouteName: 'Home',
    /* 这里定义的头部样式对栈中的每个屏幕生效除非那个屏幕类覆盖了改定义 */
    navigationOptions: {
      headerStyle: {
        backgroundColor: '#f4511e',
      },
      headerTintColor: '#fff',
      headerTitleStyle: {
        fontWeight: 'bold',
      },
    },
  }
);

→ 执行这段代码
现在,属于RouteStack的每个屏幕都在使用我们统一的品牌风格了。然很很确定的一点是,必要的情况下也必须有方法能够覆盖这些配置。

覆盖共享的navigationOptions

某个屏幕中自己定义的navigationOptions会和所属StackNavigator定义的navigationOptions合并起来最终生效,并且在屏幕中定义的navigationOptions的优先级高。我们使用这个知识点在DetailsScreen中将头部前景色和背景色做个对调:

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

    return {
      title: params ? params.otherParam : 'A Nested Details Screen',
      /* 下面的定义会覆盖StackNavigator里面的定义! */
      headerStyle: {
        backgroundColor: navigationOptions.headerTintColor,
      },
      headerTintColor: navigationOptions.headerStyle.backgroundColor,
    };
  };

  /* render function, etc */
}

使用定制组件替换标题

有时候需要对头部做更多的控制,而不仅仅是修改标题的文字和样式。比如,你可能想把标题换成一张图,或者将标题变成个按钮。这种情况下,你需要使用自定义的组件替换头部标准的标题组件。

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 表示头部渲染需要用的标题组件,
    // 现在使用你自定义的组件 LogoTitle
    headerTitle: <LogoTitle />,
  };

  /* render function, etc */
}

→ 执行这段代码

你可能奇怪为什么我们提供的组件给了headerTitle而不是像之前那样给title?这是因为headerTitleStackNavigator的一个属性,缺省是一个用于显示标题文字titleText组件。

更多配置

StackNavigator屏幕navigationOptions可用属性选项的完整清单在StackNavigator参考手册可以读到。

总结

  • 在某个屏幕组件内可通过navigationOptions静态属性定制屏幕头部。该属性可用选项的完整清单参考这里。
  • navigationOptions可以是一个对象或者一个函数。是函数的时候,被调用时它会被提供一个对象参数{ navigation, navigationOptions, screenProps }
  • StackNavigator初始化时可以提供一个navigationOptions共享给该导航器中所有的屏幕。但是每个屏幕中的静态属性navigationOptions优先级更高,可以覆盖该共享配置。

英文原文

该系列文章目录

React Navigation 基础 8 : 术语词汇表
React Navigation 基础 7 : 全屏模态
React Navigation 基础 6 : 头部按钮
React Navigation 基础 5 : 配置导航头部
React Navigation 基础 4 : 屏幕间切换参数传递
React Navigation 基础 3 : 屏幕间切换
React Navigation 基础 2 : Hello React Navigation
React Navigation 基础 1 : 开始使用

你可能感兴趣的:(React,Native,React,Navigation)