react-navigation(基础学习)(一)
一、react-navigation是干什么的?
react-navigation提供了类似于浏览器的导航窗口,可以实现跳转和回退等功能。它维护了一个堆栈,把浏览记录都放在堆栈当中,当点击返回时就会把堆栈当中的第一个去除掉,剩下的就是上一个页面。
二、react-navigation 的安装
在你的react-native项目中:
yarn add react-navigation # or with npm # npm install --save react-navigation
三、初步使用react-nativigation
react-navigation使用createStackNavigator创建一个堆栈浏览器,通过传入路径名和路径名对应的参数(如路径所对应的屏幕组件,屏幕标题栏的设置等功能。)
import React from 'react';
import { View, Text } from 'react-native';
import { createStackNavigator } 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 createStackNavigator({
Home: {
screen: HomeScreen
},
});
createStackNavigator是创建了一个组件。
由于app.js是整个程序的入口,因此一般我们在app.js中使用export default class App,将创建的堆栈浏览器赋值给一个组件变量,并在App中返回该组件。这样我们可以更多的对堆栈浏览器进行设置。
修改上述代码如下:
const RootStack = createStackNavigator({
Home: {
screen: HomeScreen
},
});
export default class App extends React.Component {
render() {
return <RootStack />;
}
}
如果路径后仅有screen一个参数,也可以简化写:
const RootStack = createStackNavigator({
Home: HomeScreen
});
添加第二条路径:
class DetailsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
</View>
);
}
}
const RootStack = createStackNavigator(
{
Home: HomeScreen,
Details: DetailsScreen,
},
{
initialRouteName: 'Home',
}
);
initialRouteName用于指定初始化的路径
四、在不同的页面进行转移
所有在createStackNavigation中创建的screen组件的props中都含有navigation这个对象,通过调用navigaition的navigate和push方法便可以跳转到指定的路径,并且可以在跳转的同时传递参数给指定的路径,被传递参数的路径可以通过getParam的方法获取上一个路径传递的参数。
示例:
import React from 'react';
import { Button, View, Text } from 'react-native';
import { createStackNavigator } 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>
);
}
}
<Button
title="Go to Details... again"
onPress={() => this.props.navigation.push('Details')}
/>
}
navigate和push的区别是:navigate首先检查堆栈浏览器中是否已经存在该页面,如果存在就不会重复添加,而push不检查堆栈浏览器中是否存在,每次都用都添加一个新的路径到堆栈浏览器中。
每当调用navigate或push到一个页面时,navigation便自动会在页面标题处出现返回按钮,当然也可以手工调用函数goBack返回,示例
class DetailsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Details... again"
onPress={() => this.props.navigation.push('Details')}
/>
<Button
title="Go to Home"
onPress={() => this.props.navigation.navigate('Home')}
/>
<Button
title="Go back"
onPress={() => this.props.navigation.goBack()}
/>
</View>
);
}
}
返回指定路径,请使用navigate,返回最上层的页面使用 navigation.popToTop()
五、页面转移同时添加参数
传递参数使用:this.props.navigation.navigate('RouteName', { /* params go here */ })或者this.props.navigation.push('RouteName', { /* params go here */ })
被传递的路径接受参数使用this.props.navigation.getParam(paramName, defaultValue),如果没有接受到参数则使用默认参数defaultValue
示例:
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. Get the param, provide a fallback value if not available */
const { navigation } = this.props;
const itemId = navigation.getParam('itemId', 'NO-ID');
const otherParam = navigation.getParam('otherParam', 'some default value');
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.push('Details', {
itemId: Math.floor(Math.random() * 100),
})}
/>
<Button
title="Go to Home"
onPress={() => this.props.navigation.navigate('Home')}
/>
<Button
title="Go back"
onPress={() => this.props.navigation.goBack()}
/>
</View>
);
}
}
可以使用this.props.navigation.state.params接受参数,但如果上调路径没有传递参数过来,就会出现null值。
六、设置标题栏
到现在为止,标题栏的格式还是默认的白色,页面时灰色,现在看如何设置标题栏的标题、字体、背景、图片等信息
在screen组件中可以调用静态属性: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 */
}
我们还可以使用参数设置标题,static navigationOptions可以接受三个参数分别是navigation(相当于this.props.navigation),screenProps(屏幕的属性)和navigationOptions(使用已经定义好的navigationOption定义默认属性),这里可以使用navigation.getParm的方法接受参数并传递给title,示例
class DetailsScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
title: navigation.getParam('otherParam', 'A Nested Details Screen'),
};
};
同时可以使用navigation.setParams来设置参数:
<Button
title="Update the title"
onPress={() => this.props.navigation.setParams({otherParam: 'Updated!'})}
/>
调整标题栏的样式:可以通过设置:
headerStyle:头部标题栏样式
headerTintColor:头部标题和返回键的颜色
headerTitleStyle:标题字体的属性,大小,粗细,字体等,示例
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Home',
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
};
上述设置仅对一个HomeScreen生效,如果要对所有的screen生效,需要在包含screen的createStackNavigator创建的堆栈浏览器组件中进行统一的配置,当然如果不希望统一的配置,可以继续在单个screen中进行配置,这时单个screen的配置将覆盖在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',
},
},
}
);
覆盖createStackNavigator的设置示例:
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 */
}
当然,也可以使用自定义的组件代替标题,如使用一张图片
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
浙公网安备 33010602011771号