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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 06:32:09