react-native 之 react-navigation 导航实现
在做react-native开发时,不免遇到导航的使用,导航分为头部导航和底部Tab标签导航,以前经常用react-native-router-flux和react-native-tab-navigator,但是最近react-native更新过快,用这第一个组件时报出警告和错误,就研究了一下react-navigation官方推荐的导航。
安装
使用
头部导航
tab底部导航
1.安装
先安装依赖
yarn add @react-navigation/native
yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
再加上这句话
import 'react-native-gesture-handler';
To finalize installation of react-native-gesture-handler, add the following at the top (make sure it’s at the top and there’s nothing else before it) of your entry file, such as index.js or App.js.
这句话意思是放在index.js or App.js最上边,如果不加入这句话,有可能出现未知错误。
- 使用
头部导航
yarn add @react-navigation/stack
新建项目后再App.js中编写
// In App.js in a new project
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>
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
在每个页面单独设置导航栏参数
React.useLayoutEffect(() => {
navigation.setOptions({
headerShown: true,
title:'我是我的页面',
headerTitleStyle:{
alignSelf:'center',
}
});
}, [navigation]);
底部导航
yarn add @react-navigation/bottom-tabs
这个同样再App.js中编写
// You can import Ionicons from @expo/vector-icons/Ionicons if you use Expo or
// react-native-vector-icons/Ionicons otherwise.
import Ionicons from 'react-native-vector-icons/Ionicons';
// (...)
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = focused
? 'ios-information-circle'
: 'ios-information-circle-outline';
} else if (route.name === 'Settings') {
iconName = focused ? 'ios-list-box' : 'ios-list';
}
// You can return any component that you like here!
return <Ionicons name={iconName} size={size} color={color} />;
},
})}
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
}}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
嵌套使用
import 'react-native-gesture-handler';
import React from 'react';
import {
View,
Text,
Button,
TextInput,
Image,
StatusBar
} from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import Index from './view/index/index'
import My from './view/my/index'
function Feed({navigation}) {
return (
<View
// eslint-disable-next-line react-native/no-inline-styles
style={{
flex: 1,
backgroundColor: '#e3e',
justifyContent: 'center',
alignItems: 'center',
}}>
<StatusBar
translucent={true}
backgroundColor="transparent"
barStyle="dark-content"/>
<Text>Feed Screen</Text>
<Button
title="Go to Profile"
onPress={() => navigation.navigate('Profile')}
/>
</View>
);
}
function Messages() {
return (
<View
// eslint-disable-next-line react-native/no-inline-styles
style={{
flex: 1,
backgroundColor: '#b33',
justifyContent: 'center',
alignItems: 'center',
}}>
<Text>Messages Screen</Text>
</View>
);
}
const Tab = createBottomTabNavigator();
function Home({navigation}) {
React.useLayoutEffect(() => {
navigation.setOptions({
headerShown: false
});
}, [navigation]);
return (
<Tab.Navigator
tabBarOptions={{
activeTintColor: '#eb4450',
inactiveTintColor: 'gray'
}}
screenOptions={({ route }) => ({
tabBarIcon: ({ focused}) => {
let iconName
if (route.name === 'Index') {
iconName = focused
? require('../images/home-o.png')
: require('../images/home.png');
} else if (route.name === 'Category') {
iconName = focused ? require('../images/category-o.png') : require('../images/category.png')
} else if (route.name === 'Cart') {
iconName = focused ? require('../images/cart-o.png') : require('../images/cart.png')
} else if (route.name === 'My') {
iconName = focused ? require('../images/my-o.png') : require('../images/my.png')
}
return <Image style={{width:25,height:25}} source={iconName} />
},
})}
>
<Tab.Screen name="Index" component={Feed} options={{ title:'首页' }} />
<Tab.Screen name="Category" component={Messages} options={{ title:'分类' }} />
<Tab.Screen name="Cart" component={Messages} options={{ title:'购物车' }} />
<Tab.Screen name="My" component={My} options={{ title:'我的' }} />
</Tab.Navigator>
);
}
function Profile({navigation}) {
return (
<View
style={{
flex: 1,
backgroundColor: '#a3e',
justifyContent: 'center',
alignItems: 'center',
}}>
<Text>Profile Screen</Text>
<Button
title="Go to Profile"
onPress={() => navigation.navigate('Settings')}
/>
</View>
);
}
function Settings() {
return (
<View
style={{
flex: 1,
backgroundColor: '#e3a',
justifyContent: 'center',
alignItems: 'center',
}}>
<Text>Settings Screen</Text>
</View>
);
}
const Stack = createStackNavigator()
const commonScreens = {
// Home: Home,
Settings: Settings,
Profile: Profile
};
export default class Router extends React.Component {
render(){
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
{Object.entries({
...commonScreens,
}).map(([name, component]) => (
<Stack.Screen key={name} name={name} component={component} />
))}
</Stack.Navigator>
</NavigationContainer>
)
}
}
写的有些混乱,只是为了以后自己看方便,后期有时间可能会修改,嘿嘿!