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

Flutter实现纵向分类栏并在旁显示菜单项的方案咨询

实现侧边分类+右侧子菜单的NavigationRail方案

直接给你可运行的示例代码,实现点击左侧分类项后,在右侧展示对应子菜单的效果:

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'NavigationRail Side Submenu',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const SideMenuPage(),
    );
  }
}

class SideMenuPage extends StatefulWidget {
  const SideMenuPage({super.key});

  @override
  State<SideMenuPage> createState() => _SideMenuPageState();
}

class _SideMenuPageState extends State<SideMenuPage> {
  // 模拟分类数据结构
  final List<Category> _categories = [
    Category(
      id: '1',
      name: 'Dashboard',
      icon: Icons.dashboard,
      subItems: ['Overview', 'Analytics', 'Reports'],
    ),
    Category(
      id: '2',
      name: 'Products',
      icon: Icons.shopping_bag,
      subItems: ['All Products', 'Add Product', 'Inventory'],
    ),
    Category(
      id: '3',
      name: 'Orders',
      icon: Icons.receipt_long,
      subItems: ['Pending', 'Completed', 'Cancelled'],
    ),
    Category(
      id: '4',
      name: 'Customers',
      icon: Icons.people,
      subItems: ['Customer List', 'Support Tickets'],
    ),
  ];

  String? _selectedCategoryId;

  @override
  Widget build(BuildContext context) {
    // 获取当前选中的分类(默认取第一个)
    final selectedCategory = _categories.firstWhere(
      (cat) => cat.id == _selectedCategoryId,
      orElse: () => _categories[0],
    );

    return Scaffold(
      body: Row(
        children: [
          // 左侧父级导航Rail
          NavigationRail(
            selectedIndex: _categories.indexWhere((cat) => cat.id == _selectedCategoryId),
            onDestinationSelected: (index) {
              setState(() {
                _selectedCategoryId = _categories[index].id;
              });
            },
            labelType: NavigationRailLabelType.all,
            destinations: _categories.map((cat) {
              return NavigationRailDestination(
                icon: Icon(cat.icon),
                selectedIcon: Icon(cat.icon, color: Colors.white),
                label: Text(cat.name),
              );
            }).toList(),
            backgroundColor: Colors.grey[100],
            selectedLabelTextStyle: const TextStyle(fontWeight: FontWeight.bold),
          ),
          const VerticalDivider(width: 1, thickness: 1),
          // 右侧子菜单展示区域
          Expanded(
            child: Container(
              padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    selectedCategory.name,
                    style: const TextStyle(
                      fontSize: 20,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 16),
                  Expanded(
                    child: ListView.builder(
                      itemCount: selectedCategory.subItems.length,
                      itemBuilder: (context, index) {
                        final subItem = selectedCategory.subItems[index];
                        return ListTile(
                          title: Text(subItem),
                          onTap: () {
                            // 这里可以添加子项点击后的业务逻辑
                            print('选中子项: $subItem');
                          },
                          leading: const Icon(Icons.arrow_right),
                        );
                      },
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

// 分类数据模型
class Category {
  final String id;
  final String name;
  final IconData icon;
  final List<String> subItems;

  Category({
    required this.id,
    required this.name,
    required this.icon,
    required this.subItems,
  });
}

核心逻辑说明

  1. 用Row拆分界面:左侧是NavigationRail父分类导航,右侧是子菜单展示区
  2. 通过_selectedCategoryId维护当前选中的父分类状态,点击Rail项时更新状态
  3. 右侧子菜单根据选中的分类动态渲染对应的子项列表
  4. 用Expanded让右侧区域占满剩余宽度,适配不同屏幕尺寸

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 10:15:25