You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 01:33:29