Flutter中Drawer+ListTile菜单选中状态重置问题求助
问题解决:Drawer中ListTile选中状态关闭后重置的修复
问题原因
你的MenuList组件自己维护选中状态_selectedIndex,但Drawer每次关闭后重新打开时,MenuList的State会被重新初始化,导致_selectedIndex回到初始值0,选中样式丢失。
解决方案
将选中状态提升到父组件(MobileDashboard)中管理,父组件的状态不会随Drawer的关闭/打开而销毁,再把选中状态传递给MenuList组件。
修改后的代码
1. menu_list.dart
将MenuList改为无状态组件,接收父组件传入的选中索引:
class MenuList extends StatelessWidget { final Function(int, String) onTap; final List<Map<String, dynamic>> menu; final int selectedIndex; // 接收父组件的选中索引 const MenuList({ super.key, required this.onTap, required this.menu, required this.selectedIndex, }); Widget buildListTile(Map<String, dynamic> item, int index) { return ListTile( title: Text( item["title"], style: TextStyle( color: selectedIndex == index ? Colors.deepOrangeAccent : Colors.grey, ), ), leading: Icon( item['leading'], color: selectedIndex == index ? Colors.deepOrangeAccent : Colors.grey, ), tileColor: Colors.white, onTap: () { onTap(index, item['title']); }, ); } @override Widget build(BuildContext context) { return ListView.builder( itemCount: menu.length, itemBuilder: (BuildContext context, int index) { return buildListTile(menu[index], index); }, ); } }
2. mDashboard.dart
在父组件中维护选中索引,并传递给MenuList:
class MobileDashboard extends StatefulWidget { @override State<MobileDashboard> createState() => _MobileDashboardState(); } class _MobileDashboardState extends State<MobileDashboard> { final _auth = FirebaseAuth.instance; final PageController _pageController = PageController(initialPage: 0); String _selectedTitle = ''; int _selectedIndex = 0; // 父组件维护选中索引 final List<Map<String, dynamic>> menu = [ {'title': 'Playlists', 'leading': Icons.featured_play_list}, {'title': 'Menu..', 'leading': Icons.send}, {'title': 'Logout', 'leading': Icons.logout}, ]; void handleTap(int index, String title) { setState(() { _selectedIndex = index; // 更新父组件的选中状态 _selectedTitle = title; }); Get.back(result: false); // 关闭Drawer } @override void initState() { _selectedTitle = 'Playlists'; super.initState(); } @override void dispose() { _pageController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( endDrawer: Drawer( child: ListView( children: [ SizedBox( height: 100, child: DrawerHeader( child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Expanded( child: Align( alignment: Alignment.centerLeft, child: IconButton( onPressed: () { Get.back(result: false); }, icon: const Icon(CupertinoIcons.xmark), ), ), ), const Icon(Icons.info_outline, size: 24, color: Colors.grey), const SizedBox(width: 27.3), SizedBox( width: 28, height: 28, child: CircleAvatar( backgroundImage: AssetImage('assets/loginBG.png'), ), ), ], ), ), ), SizedBox( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, child: MenuList( onTap: handleTap, menu: menu, selectedIndex: _selectedIndex, // 传递选中索引给MenuList ), ), ], ), ), // 此处省略原Scaffold的其他内容(如appBar、body等) ); } }
原理说明
父组件MobileDashboard的生命周期独立于Drawer,其维护的_selectedIndex状态不会因Drawer关闭而丢失。每次打开Drawer时,MenuList会根据父组件传入的selectedIndex渲染对应的选中样式,从而保持状态一致。
内容的提问来源于stack exchange,提问作者JYX
相关产品推荐
相关产品推荐

