屏幕组件可以有一个静态属性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.params
从navigation
获取参数,现在我们使用这种方式获取一个参数把它用作标题 :
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上面的例子我们只需要navigation
,但有些情况下你可能需要screenProps
或者navigationOptions
。
##使用setParams
更新navigationOptions
我们经常需要从挂载的屏幕自己内部更新当前活跃屏幕的navigationOptions
配置,像这个样子操作:
/* 在render()里面 */
<Button
title="更新头部标题"
onPress={() => this.props.navigation.setParams({otherParam: 'Updated!'})}
/>
/**结合上面的例子使用这个例子,上面的例子中,头部标题设置成等于 params.otherParam **/
→ 执行这段代码
定制屏幕自己的头部样式有三个关键属性: headerStyle
,headerTintColor
和headerTitleStyle
。
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 */
}
→执行这段代码
这里有一些事情需要注意:
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
?这是因为headerTitle
是StackNavigator
的一个属性,缺省是一个用于显示标题文字title
的Text
组件。
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 : 开始使用