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

Flutter中如何实现点击侧边栏触发的二级自定义菜单

Flutter 自定义带二级菜单的侧边栏实现方案

1. 定义菜单数据结构

先把主菜单和对应的二级菜单关联起来,创建数据模型类统一管理菜单信息:

class MenuItem {
  final IconData icon;
  final String title;
  final List<String>? subItems; // 二级菜单列表,为空则表示该主菜单无二级项

  MenuItem({required this.icon, required this.title, this.subItems});
}

2. 更新状态变量

在_SideMenuState中添加状态变量,用于跟踪菜单的选中和展开状态:

final List<MenuItem> menuItems = [
  MenuItem(icon: Icons.home, title: '首页'),
  MenuItem(icon: Icons.settings, title: '设置', subItems: ['账号设置', '通知设置', '隐私设置']),
  MenuItem(icon: Icons.dashboard, title: '仪表盘', subItems: ['数据概览', '统计报表']),
  // 根据需求添加更多菜单
];
int? expandedIndex; // 记录当前展开的主菜单索引,null表示无展开菜单
late List<bool> selected; // 主菜单选中状态

@override
void initState() {
  super.initState();
  // 初始化选中状态,默认所有主菜单都未选中
  selected = List.generate(menuItems.length, (index) => false);
}

3. 修改菜单点击逻辑

更新select方法,同时处理主菜单选中切换和二级菜单的展开/收起:

void select(int index) {
  setState(() {
    // 重置所有主菜单的选中状态
    for (int i = 0; i < selected.length; i++) {
      selected[i] = false;
    }
    selected[index] = true;

    // 切换二级菜单状态:点击当前展开的菜单则收起,否则展开(仅当该菜单有二级项时)
    if (expandedIndex == index) {
      expandedIndex = null;
    } else {
      expandedIndex = menuItems[index].subItems != null ? index : null;
    }
  });
}

4. 重构UI布局,添加二级菜单

修改build方法,在Stack中加入二级菜单容器,通过Positioned定位在主侧边栏右侧:

@override
Widget build(BuildContext context) {
  return Stack(
    children: [
      // 页面背景容器
      Container(color: Colors.white),
      // 二级菜单:仅当有展开的菜单且该菜单存在二级项时显示
      if (expandedIndex != null && menuItems[expandedIndex!].subItems != null)
        Positioned(
          left: 101.0, // 与主侧边栏宽度一致,保证对齐
          top: 0,
          bottom: 0,
          child: AnimatedContainer(
            duration: const Duration(milliseconds: 300),
            width: 200.0,
            color: Colors.grey[100],
            child: ListView(
              padding: EdgeInsets.zero,
              children: menuItems[expandedIndex!].subItems!
                  .map((subItem) => ListTile(
                        title: Text(subItem),
                        onTap: () {
                          // 二级菜单点击逻辑,可根据需求添加选中状态
                          setState(() {
                            // 示例:记录选中的二级菜单索引
                            // selectedSubIndex = ...;
                          });
                        },
                      ))
                  .toList(),
            ),
          ),
        ),
      // 主侧边栏容器
      Container(
        height: MediaQuery.of(context).size.height,
        width: 101.0,
        decoration: const BoxDecoration(
          color: AppColors.mainBlueColor,
        ),
        child: ListView(
          padding: EdgeInsets.zero,
          children: List.generate(
            menuItems.length,
            (index) => Tooltip(
              message: menuItems[index].title,
              child: NavBarItem(
                icon: menuItems[index].icon,
                selected: selected[index],
                // 给有二级菜单的项添加箭头图标,提示展开状态
                trailing: menuItems[index].subItems != null
                    ? Icon(
                        expandedIndex == index ? Icons.arrow_right : Icons.arrow_drop_down,
                        color: Colors.white,
                      )
                    : null,
                onTap: () => select(index),
              ),
            ),
          ),
        ),
      ),
    ],
  );
}

可选优化

  • 可以给二级菜单的选中状态添加样式,比如背景色、文字颜色变化
  • 给主侧边栏的箭头图标添加旋转动画,增强交互反馈
  • 调整二级菜单的宽度、背景色等样式,匹配你的设计需求

内容的提问来源于stack exchange,提问作者Hashir Aslam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 20:40:41