以下内容参照StackNavigator官网文档 链接
Hello React Navigation
- 参照官网,如果要支持安卓,要先下载react-navigation这个库,在工程路径下执行:
npm install --save react-navigation
// 如果安装了yarn 也可以使用以下命令
yarn add react-navigation
-
React Navigation中用到了StackNavigator,即创建了一个类似于浏览器的历史栈的对象。StackNavigator和web历史栈的一个关键区别是可以手势和动画效果。
-
创建基本导航栈
import React from 'react';
import { View, Text } from 'react-native';
import { StackNavigator } from 'react-navigation';
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
}
export default StackNavigator({
Home: { // 这个名字任意
screen: HomeScreen, // 必须有screen这个组件
},
});
因为StackNavigator()返回一个组件,所以可以直接通过export导出。显示这个栈中的内容更,目前只有一个空的导航,和中间的文字。
在ReactNative中,在App.js中export的组件是整个App的入口(或者叫根组件),通常不会直接导出一个'导航栈'组件,而是用另外一个组件渲染'导航栈'组件。修改如下:
const RootStack = StackNavigator({
Home: {
screen: HomeScreen,
},
});
export default class App extends React.Component {
render() {
return <RootStack />;
}
}
- 添加第二屏
class DetailsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
</View>
);
}
}
const RootStack = StackNavigator(
{
Home: {
screen: HomeScreen,
},
Details: {
screen: DetailsScreen,
},
},
{
initialRouteName: 'Home',
}
);
第一个参数,表示导航栈内有哪些视图;第二个是配置参数(可选)
修改initialRouteName后面的名称,可以发现初始化的页面不同。
下节讨论如何在双屏间切换。
双屏间切换
- 在主屏设置Button,并添加点击,关联到this.props.navigation.navigate('Details')
import React from 'react';
import { Button, View, Text } from 'react-native';
import { StackNavigator } from 'react-navigation';
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => this.props.navigation.navigate('Details')}
/>
</View>
);
}
}
this.props.navigation,这个属性会被设置到所有StackNavigator中的页面
navigate('Details'),将页面名称传入该方法,可以跳转到指定页面
只能跳转到StackNavigator中的界面,如果该名称传入错误,什么也不会发生。
如果在Details页面再添加一个Button跳转到Details页面,页面会一直被添加。
- StackNavigator会在非首屏提供一个返回箭头,提供返回操作。也可以通过添加按钮关联goback返回。此外,StackNavigator自动关联了安卓的返回键,点击设备的返回键也可以返回。
class DetailsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title = 'GO TO DETAIL AGAIN'
onPress = {()=>this.props.navigation.navigate('Details')}
/>
<Button
title="Go back"
onPress={() => this.props.navigation.goBack()}
/>
</View>
);
}
}
测试发现,自己设置返回正常,但点击头部箭头返回在MX4上很慢,并不是不执行,但是要间隔很久,实测用了12s。。。目前没有找到原因。(看看自定义能不能解决)
运行时遇到一个Unknown error: not all success patterns were matched错误,重新加载也不行,直接运行也不行。 用命令行跑了一下,发现找不到设备。。。重新拔插了一下usb就好了。
传递参数
- 通过在调用navigate方法时传入一个对象
this.props.navigation.navigate('RouteName', { /* params go here */ })
- 读取参数
this.props.navigation.state.params
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => {
/* 1. Navigate to the Details route with params */
this.props.navigation.navigate('Details', {
itemId: 86,
otherParam: 'anything you want here',
});
}}
/>
</View>
);
}
}
class DetailsScreen extends React.Component {
render() {
/* 2. Read the params from the navigation state */
const { params } = this.props.navigation.state;
const itemId = params ? params.itemId : null;
const otherParam = params ? params.otherParam : null;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Text>itemId: {JSON.stringify(itemId)}</Text>
<Text>otherParam: {JSON.stringify(otherParam)}</Text>
<Button
title="Go to Details... again"
onPress={() => this.props.navigation.navigate('Details')}
/>
<Button
title="Go back"
onPress={() => this.props.navigation.goBack()}
/>
</View>
);
}
}
自定义header bar
- 每个组件有一个静态属性叫navigationOptions,可以通过这个配置一些参数,例如title (ios默认会居中,android居左)
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Home',
};
/* render function, etc */
}
class DetailsScreen extends React.Component {
static navigationOptions = {
title: 'Details',
};
/* render function, etc */
}
-
将this.props放入navigationOptions中使用看起来很方便,但因为这是个静态属性,所以实际上并不会关联到任何实例,自然也不会有props属性。这里需要将navigationOptions变成一个方法,React Navigation会通过一个包含{navigation, navigationOptions, screenProps}的对象调用它。
-
传递参数设置navigationOptions
class DetailsScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
// 注意params是带大括号的
const { params } = navigation.state;
return {
title: params ? params.otherParam : 'A Nested Details Screen',
}
};
/* render function, etc */
}
The argument that is passed in to the navigationOptions function is an object with the following properties:
navigation - The navigation prop for the screen, with the screen's route at navigation.state.
screenProps - The props passing from above the navigator component(上层组件传过来的参数)
navigationOptions - The default or previous options that would be used if new values are not provided
上面只用到了navigation属性
- 在当前屏幕对navigationOptions进行更新
<Button
title="Update the title"
onPress={() => this.props.navigation.setParams({otherParam: 'Updated!'})}
/>
通过setParams设置了一个新的对象
- 调整头部样式
主要用到三个属性
headerStyle:设置包裹头部view的样式,可以设置背景颜色
headerTintColor: 渲染返回键、标题的颜色。
headerTitleStyle: 设置文字、字体、粗细(fontWeight)?
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Home',
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
};
/* render function, etc */
}
这种设置方式只对当前页面有效。
- 如果要配置对所有导航页都有效的样式,应该在StackNavigator的第二个参数中配置
const RootStack = StackNavigator(
{
Home: {
screen: HomeScreen,
},
Details: {
screen: DetailsScreen,
},
},
{
initialRouteName: 'Home',
/* The header config from HomeScreen is now here */
navigationOptions: {
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
},
}
);
这样所有的样式就一样了,如果某个页面要设置特殊样式,可以单独设置。也可以通过将公共的navigationOptions 通过对象传入进行修改。
- 自定义一个组件作为标题
// 定义一个标题
class LogoTitle extends React.Component {
render() {
return (
<Text style ={ {flex:1, fontSize:30,color:'green',textAlign:'center'}}>
标题
</Text>
);
}
}
class HomeScreen extends React.Component {
static navigationOptions = {
// title: 'Home',
headerTitle:<LogoTitle/>,
};
...以下省略...
相关API可以查看StackNavigator reference
网友评论