React Navigation V5
Installation
- 安装
npm install @react-navigation/native
- 安装依赖:
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
- 更新一下 Cocoapods
npx pod-install ios
- 在rn项目的最起始入口处加一句
import 'react-native-gesture-handler';
example:
import 'react-native-gesture-handler';
import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
export default function App() {
return (
<NavigationContainer>{/* Rest of your app code */}</NavigationContainer>
);
}
Hello React Navigation
- 安装|Installing the stack navigator library.
npm install @react-navigation/stack
- 使用
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
// code
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
createStackNavigator 是一个方法,返回一个对象,这个对象有两个属性:Screen、Navigator,他们都是用来配置路由的react 组建,Navigator 应该包含Screen的elements来配置路由 NavigationContainer 是用来管理导航树和导航状态的容器组建,该组件必须封装所有导航器结构
example
import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} options={{ title: 'Overview' }}/>
// 这里的DetailsScreen 页面 没有写
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
initialRouteName 初始化起始页面
页面跳转
// 跳转到某个页面,如Setting页面,不过跳转多少次,仅会打开一次这个页面,
// 如果在当前页面跳转,没有效果
this.props.navigation.navigate('Setting')
// 跳转到某个页面,如Setting页面,跳转多次会打开多个Setting页面,
// 在Setting页面跳转会再次打开这个页面
this.props.navigation. push('Setting')
// 返回上一个页面
navigation.goBack()
// 返回到某一个页面,如Home页面,注意不要用push
navigate('Home')
// 返回到第一个页面
navigation.popToTop()
跳转参数处理
// 传参
navigation.navigate('Details', {
itemId: 86,
otherParam: 'anything you want here',
});
// 取参
const { itemId, otherParam } = route.params;
// 更新参数
navigation.setParams({
query: 'someText',
})
// 初始化默认页面参数
<Stack.Screen
name="Details"
component={DetailsScreen}
initialParams={{ itemId: 42 }}
/>
向前一个页面传递参数
// home->detail->home
// 通过navigate 把参数传递回去
navigation.navigate({
name: 'Home',
params: { post: postText },
merge: true,
});
导航栏配置
- 设置导航栏标题
// options 中的titlte
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'My home' }}
/>
<Stack.Screen
name="Profile"
component={ProfileScreen}
options={({ route }) => ({ title: route.params.name })}
/>
</Stack.Navigator>
// navigation.setOptions 设置title
this.props.navigation.setOptions({ title: 'Updated!' })
- 导航栏样式
- headerStyle 导航栏样式
- headerTintColor 导航栏标题颜色
- headerTitleStyle 导航栏标题样式
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{
title: 'My home',
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
}}
/>
</Stack.Navigator>
- screenOptions 配置公共导航栏样式
- headerStyle、headerTitleStyle、headerTintColor 同上
<NavigationContainer>
<Stack.Navigator
initialRouteName={'Home'}
screenOptions={{
headerStyle: {
backgroundColor: '#00FF00',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
}}>
<Stack.Screen name="Home" component={HomePage} options={{
title: 'My home',
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
}} />
<Stack.Screen name="Setting" component={SettingPage} options={{ title: 'Overview' }}/>
</Stack.Navigator>
</NavigationContainer>
- 用自定义组件替换标题
headerTitle 接受一个组件,替换导航栏标题
function LogoTitle() {
return (
<Image
style={{ width: 50, height: 50 }}
source={require('@expo/snack-static/react-native-logo.png')}
/>
);
}
function StackScreen() {
return (
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ headerTitle: props => <LogoTitle {...props} /> }}
/>
</Stack.Navigator>
);
}
导航栏按钮
// headerRight 接受一个方法,方法返回组件,可以用来在右边放按钮、或者其他的...
// 注意headerRight 接受的方法中的this并不指向组件的this
<Stack.Screen
name="Setting"
component={SettingPage}
options={{
headerTitle: null,
headerRight:() => (
<View
style={{
width:30,
height:30,
marginRight:15,
backgroundColor:'green'
}}
/>
)
}}
/>
// 可以在组件中使用setOptions,从而指向this,也可以使用hook...(更多的可以动动脑,或者查阅相关资料)
componentDidMount() {
this.props.navigation.setOptions({
headerRight: this._getRightBtn,
})
}
_getRightBtn=()=>{
return (
<Button onPress={() => {
this.setState({
count:5
})
}} title="Update count11" />
)
}
- headerBackTitle 自定义返回按钮的文案
- headerBackImage 自定义返回按钮的图片
- headerLeft 自定义返回按钮 ,参考headerRight
- headerTitle 自定义标题部分的视图
Nesting navigators 嵌套导航栏
function Home() {
return (
<Tab.Navigator>
<Tab.Screen name="Feed" component={Feed} />
<Tab.Screen name="Messages" component={Messages} />
</Tab.Navigator>
);
}
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Profile" component={Profile} />
<Stack.Screen name="Settings" component={Settings} />
</Stack.Navigator>
</NavigationContainer>
);
}
路由嵌套如下
- Stack.Navigator
- Home (Tab.Navigator)
- Feed (Screen)
- Messages (Screen)
- Profile (Screen)
- Settings (Screen)
- Home (Tab.Navigator)
嵌套路由的跳转
navigation.navigate('Root', {
screen: 'Settings',
params: {
screen: 'Sound',
params: {
screen: 'Media',
},
},
});
headerShown 在嵌套路由器中,会存在部分页面导航栏需要隐藏,是有这个headerShown:false来隐藏导航栏