React Native中如何实现类似示例图的三点导航菜单及子菜单?
在React Native中实现点击三点触发的导航菜单(含子菜单)
可以通过两种方式实现你要的效果:使用成熟的第三方库,或者自定义组件开发,以下是具体实现方案:
方式一:使用@react-native-menu/menu库(推荐)
这个库专门用于实现原生级别的菜单组件,支持子菜单嵌套,适配iOS和Android平台。
步骤1:安装依赖
# npm 安装 npm install @react-native-menu/menu --save # iOS 需额外执行 cd ios && pod install && cd ..
步骤2:代码实现
import React from 'react'; import { View, Text, StyleSheet } from 'react-native'; import { Menu, MenuButton, MenuItem } from '@react-native-menu/menu'; const ThreeDotMenu = () => { return ( <View style={styles.container}> {/* 右上角三点按钮 */} <Menu button={<MenuButton style={styles.menuButton} title="⋮" />} > <MenuItem onPress={() => alert('点击了首页')}>首页</MenuItem> <MenuItem onPress={() => alert('点击了我的')}>我的</MenuItem> {/* 嵌套子菜单 */} <Menu title="设置"> <MenuItem onPress={() => alert('点击了账号设置')}>账号设置</MenuItem> <MenuItem onPress={() => alert('点击了通知设置')}>通知设置</MenuItem> <MenuItem onPress={() => alert('点击了隐私设置')}>隐私设置</MenuItem> </Menu> <MenuItem onPress={() => alert('点击了退出登录')}>退出登录</MenuItem> </Menu> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'flex-end', alignItems: 'flex-end', padding: 16, backgroundColor: '#f5f5f5', }, menuButton: { fontSize: 24, padding: 8, }, }); export default ThreeDotMenu;
方式二:自定义实现(无第三方依赖)
如果不想引入第三方库,可以用Modal结合基础组件手动实现菜单效果。
代码实现
import React, { useState } from 'react'; import { View, Text, TouchableOpacity, Modal, StyleSheet, Dimensions } from 'react-native'; const { width } = Dimensions.get('window'); const CustomThreeDotMenu = () => { const [menuVisible, setMenuVisible] = useState(false); const [subMenuVisible, setSubMenuVisible] = useState(false); return ( <View style={styles.container}> {/* 三点触发按钮 */} <TouchableOpacity style={styles.menuButton} onPress={() => setMenuVisible(!menuVisible)} > <Text style={{ fontSize: 24 }}>⋮</Text> </TouchableOpacity> {/* 主菜单Modal */} <Modal visible={menuVisible} transparent={true} animationType="fade" onRequestClose={() => setMenuVisible(false)} > {/* 点击空白处关闭菜单 */} <TouchableOpacity style={styles.modalOverlay} onPress={() => { setMenuVisible(false); setSubMenuVisible(false); }} > <View style={styles.menuContainer}> {/* 主菜单项 */} <TouchableOpacity style={styles.menuItem} onPress={() => { alert('点击了首页'); setMenuVisible(false); }}> <Text>首页</Text> </TouchableOpacity> <TouchableOpacity style={styles.menuItem} onPress={() => { alert('点击了我的'); setMenuVisible(false); }}> <Text>我的</Text> </TouchableOpacity> {/* 带展开子菜单的项 */} <TouchableOpacity style={styles.menuItem} onPress={() => setSubMenuVisible(!subMenuVisible)} > <Text>设置 ▼</Text> </TouchableOpacity> {/* 子菜单 */} {subMenuVisible && ( <View style={styles.subMenuContainer}> <TouchableOpacity style={styles.subMenuItem} onPress={() => { alert('点击了账号设置'); setMenuVisible(false); }}> <Text>账号设置</Text> </TouchableOpacity> <TouchableOpacity style={styles.subMenuItem} onPress={() => { alert('点击了通知设置'); setMenuVisible(false); }}> <Text>通知设置</Text> </TouchableOpacity> </View> )} <TouchableOpacity style={styles.menuItem} onPress={() => { alert('点击了退出登录'); setMenuVisible(false); }}> <Text>退出登录</Text> </TouchableOpacity> </View> </TouchableOpacity> </Modal> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'flex-end', alignItems: 'flex-end', padding: 16, backgroundColor: '#f5f5f5', }, menuButton: { padding: 8, }, modalOverlay: { flex: 1, justifyContent: 'flex-end', alignItems: 'flex-end', padding: 16, backgroundColor: 'rgba(0,0,0,0.3)', }, menuContainer: { width: width * 0.4, backgroundColor: '#fff', borderRadius: 8, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.2, shadowRadius: 4, elevation: 5, }, menuItem: { padding: 14, borderBottomWidth: 1, borderBottomColor: '#eee', }, subMenuContainer: { paddingLeft: 16, backgroundColor: '#f8f8f8', }, subMenuItem: { padding: 12, borderBottomWidth: 1, borderBottomColor: '#eee', }, }); export default CustomThreeDotMenu;
自定义实现说明
- 用
Modal实现弹出层,通过transparent属性设置半透明背景 - 点击空白区域可以关闭菜单,提升交互体验
- 子菜单通过
useState控制显示状态,用缩进样式区分层级
内容的提问来源于stack exchange,提问作者Abhishek Deshmukh
相关产品推荐
相关产品推荐

