Flutter实现纵向分类栏并在旁显示菜单项的方案咨询
直接给你可运行的示例代码,实现点击左侧分类项后,在右侧展示对应子菜单的效果:
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, }); }
核心逻辑说明
- 用
Row拆分界面:左侧是NavigationRail父分类导航,右侧是子菜单展示区 - 通过
_selectedCategoryId维护当前选中的父分类状态,点击Rail项时更新状态 - 右侧子菜单根据选中的分类动态渲染对应的子项列表
- 用
Expanded让右侧区域占满剩余宽度,适配不同屏幕尺寸
内容的提问来源于stack exchange,提问作者Noct
相关产品推荐
相关产品推荐

