这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战
全局模态框
类似于
Alert.alert("...")
,显示临时阻止于主视图交互的内容
创建堆栈模态框
import * as React from 'react';
import { View, Text, Button } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
// 首页
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{ fontSize: 30 }}>This is the home screen!</Text>
<Button
onPress={() => navigation.navigate('MyModal')}
title="Open Modal"
/>
</View>
);
}
// 模态框
function ModalScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{ fontSize: 30 }}>This is a modal!</Text>
<Button onPress={() => navigation.goBack()} title="Dismiss" />
</View>
);
}
// 详情页
function DetailsScreen() {
return (
<View>
<Text>Details</Text>
</View>
);
}
// 创建堆栈式导航
const MainStack = createStackNavigator();
const RootStack = createStackNavigator();
function MainStackScreen() {
return (
<MainStack.Navigator>
<MainStack.Screen name="Home" component={HomeScreen} />
<MainStack.Screen name="Details" component={DetailsScreen} />
</MainStack.Navigator>
);
}
function App() {
return (
<NavigationContainer>
<RootStack.Navigator mode="modal" headerMode="none">
<RootStack.Screen name="Main" component={MainStackScreen} />
<RootStack.Screen name="MyModal" component={ModalScreen} />
</RootStack.Navigator>
</NavigationContainer>
);
}
export default App;
上面代码中,MainStackScreen
组件作为RootstackScreen
内的屏幕! 通过这样做,我们嵌套另一个堆栈导航器内的堆栈导航器。因为我们希望为模态使用不同的转换方式。 由于RootStackScreen
呈现堆栈导航器并具有自己的标题和一些其他属性。
标签导航
很多时候一个应用都会或多或少的出现标签导航,比如底部一排快捷标签导航。
$ npm install @react-navigation/bottom-tabs
or
$ yarn add @react-navigation/bottom-tabs
常用属性
tabBarIcon
设置标签导航的图标,包含是否选中、颜色和字体大小等等tabBarOptions
activeTintColor
选中时的标题字体颜色inactiveTintColor
未选中时的标题字体颜色size
字体大小
createBottomTabNavigator
创建标签导航按钮,返回两个参数Navigator
和`Screen``tabBarBadge
设置徽章,接受字符串或者数字的文本tabBarBadgeStyle
设置徽章样式
底部导航案例
实现底部两个标签导航
HomeScreen
和SettingsScreen
import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
function HomeScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
);
}
function SettingsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
);
}
// 创建标签导航
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
自定义标签导航的样式
比如自定义文字颜色、文字大小、粗细、字体、选中和未选中时的图标
import * as React from 'react';
import { Text, View } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { NavigationContainer } from '@react-navigation/native';
function HomeScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
);
}
function SettingsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
);
}
const Tab = createBottomTabNavigator();
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 * as React from 'react';
import { Text, View } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
function HomeScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
);
}
function SettingsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
if (route.name === 'Home') {
return (
<Ionicons
name={
focused
? 'ios-information-circle' // 选中时的图标
: 'ios-information-circle-outline' // 未选中时的图标
}
size={size}
color={color}
/>
);
} else if (route.name === 'Settings') {
return (
<Ionicons
name={focused ? 'ios-list-box' : 'ios-list'}
size={size}
color={color}
/>
);
}
},
})}
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
}}
>
<Tab.Screen
name="Home"
component={HomeScreen}
options={{
// 设置徽章
tabBarBadge: 3
}}
/>
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
效果图如下:
事件跳转
类似于web中的a标签跳转
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('Settings')}
/>
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
</View>
);
}
抽屉式导航
效果如下:
常用属性 文档
createDrawerNavigator
创建一个drawer导航,返回两个参数Navigator和Screentitle
drawerLabel
drawerLabel
swiperEnabled
gestureEnabled
header
headerShow
headerTitle
headerTitleAlign
headerTitleAllowFontScaling
headerTitleStyle
headerLeft
headerPressColorAndroid
headerStyle
headerStatusBarHeight
unmountOnBlur
事件
-
drawerOpen. 此事件会在drawer打开时触发
avigation.addListener('drawerOpen', (event) => { // Do something });
-
drawerClose 此事件会在drawer关闭时触发
navigation.addListener('drawerClose', (event) => { // Do something });
-
openDrawer() 打开drawer方法
navigation.openDrawer();
-
closeDrawer() 关闭drawer方法
navigation.closeDrawer();
-
toggleDrawer() 状态切换;如果关闭,打开抽屉窗格,如果打开,关闭抽屉窗格。
navigation.toggleDrawer();
-
jumpTo() 跳转到抽屉导航器中的现有屏幕。可接受两个参数,第一个是被跳转到的屏幕组件的名称,第二个参数是可选传递参数对象
navigation.jumpTo('Profile', { owner: 'Satya' });
-
useIsDrawerOpen() 检测drawer是否打开,只能在函数组件中使用;
示例
// drawer.tsx
import React, { Component } from 'react';
import { createDrawerNavigator } from '@react-navigation/drawer';
import Detail from '../detail/Detail';
import CustomTitleBar from '../custom-title-bar/CustomTitleBar';
export type DrawerParamList = {
CustomTitleBar: undefined;
Detail: undefined;
};
const Drawers = createDrawerNavigator<DrawerParamList>();
export default class Drawer extends Component {
render() {
return (
<Drawers.Navigator initialRouteName="CustomTitleBar">
<Drawers.Screen
name="CustomTitleBar"
component={CustomTitleBar}
/>
<Drawers.Screen name="Detail" component={Detail} />
</Drawers.Navigator>
);
}
}
// CustomTitlebar
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { Button } from '@ant-design/react-native';
import { DrawerNavigationProp } from '@react-navigation/drawer';
import { DrawerParamList } from '../../pages/drawer/Drawer';
export type IProps = {
navigation: DrawerNavigationProp<DrawerParamList>;
};
interface IState {
isOpen: boolean;
}
export default class CustomTitleBar extends Component<IProps> {
state: IState = {
isOpen: false,
};
// 响应事件drawer开闭事件
handleClickOpenOrClose() {
const { navigation } = this.props;
navigation.toggleDrawer();
}
render() {
const { isOpen } = this.state;
return (
<View>
<Text>自定义头部组件</Text>
<Button onPress={() => this.handleClickOpenOrClose()}>
{isOpen ? 'close' : 'open'} drawer
</Button>
</View>
);
}
}
标签按钮导航
屏幕底部的一个简单的标签栏,可让您在不同的路由之间切换。 路线懒惰初始化 - 它们的屏幕组件未安装,直到它们首先聚焦。
@react-navigation/bottom-tabs依赖于@react-navigation/native
文档: 官网
顶部标签切换
可通过点击选项卡或水平滑动来在不同的路由之间切换。 过渡默认情况下会动画。如下:
import React, { Component } from 'react';
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
import Home from '../home/Home';
import List from '../list/List';
import Found from '../found/Found';
export type TopTabParmasList = {
Home: undefined;
List: undefined;
Found: undefined;
};
const Tab = createMaterialTopTabNavigator<TopTabParmasList>();
export default class TopTab extends Component {
render() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="List" component={List} />
<Tab.Screen name="Found" component={Found} />
</Tab.Navigator>
);
}
}