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

Flutter中在Drawer Header添加Dropdown Button遇setState错误求助

问题原因

你的MainDrawer是StatelessWidget,这类组件没有内部状态管理能力,无法调用setState方法——而DropdownButtonFormField需要通过setState更新选中状态,触发组件重新渲染,这就是错误的根源。

解决方案

提供两种可行的修复方式,根据你的需求选择:


方案一:将MainDrawer改为StatefulWidget

把整个抽屉组件改为有状态组件,统一管理Dropdown的状态:

import 'package:flutter/material.dart';
import 'package:test/Screens/change_password_screen.dart';
import 'package:test/Screens/login_screen.dart';

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

  @override
  State<MainDrawer> createState() => _MainDrawerState();
}

class _MainDrawerState extends State<MainDrawer> {
  // 把状态变量移到State类中
  List<String> itemsList = ['1', '2'];
  String? selectedItem = '1';

  @override
  Widget build(BuildContext context) {
    return Drawer(
      width: 250,
      child: ListView(
        children: <Widget>[
          DrawerHeader(
            decoration: BoxDecoration(
                border: Border.all(color: Colors.white),
                image: const DecorationImage(
                  image: AssetImage("assets/images/logo.png"),
                )),
            // 用Column同时容纳文本和Dropdown组件
            child: Column(
              mainAxisAlignment: MainAxisAlignment.end,
              children: [
                const Text(
                  "Example@hotmail.com",
                  style: TextStyle(
                    color: Colors.black,
                    fontSize: 14.0,
                    fontWeight: FontWeight.normal,
                  ),
                ),
                const SizedBox(height: 10),
                Container(
                  padding: const EdgeInsets.symmetric(horizontal: 25.0, vertical: 0.0),
                  child: SizedBox(
                    height: 40,
                    child: DropdownButtonFormField<String>(
                        decoration: const InputDecoration(
                            enabledBorder: OutlineInputBorder(
                                borderSide: BorderSide(
                          width: 1,
                          color: Colors.grey,
                        ))),
                        value: selectedItem,
                        items: itemsList
                            .map((item) => DropdownMenuItem(
                                  value: item,
                                  child: Text(item),
                                ))
                            .toList(),
                        onChanged: (item) => setState(() => selectedItem = item)),
                  ),
                ),
              ],
            ),
          ),
          const Divider(
            color: Colors.black,
            height: 10,
            thickness: 1,
          ),
          // 以下ListTile和Divider代码保持不变
          ListTile(
            leading: Image.asset("assets/images/exampla.png"),
            title: const Text(
              'exampla',
              style: TextStyle(
                color: Colors.black,
                fontSize: 14.0,
                fontWeight: FontWeight.normal,
              ),
            ),
            onTap: null,
          ),
          const Divider(color: Colors.black, height: 10, thickness: 1),
          ListTile(
            leading: Image.asset("assets/images/examplb.png"),
            title: const Text(
              'examplb',
              style: TextStyle(
                color: Colors.black,
                fontSize: 14.0,
                fontWeight: FontWeight.normal,
              ),
            ),
            onTap: null,
          ),
          const Divider(color: Colors.black, height: 10, thickness: 1),
          ListTile(
            leading: Image.asset("assets/images/examplc.png"),
            title: const Text(
              'examplc',
              style: TextStyle(
                color: Colors.black,
                fontSize: 14.0,
                fontWeight: FontWeight.normal,
              ),
            ),
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => const ExamplzScreen()),
              );
            },
          ),
          const Divider(color: Colors.black, height: 10, thickness: 1),
          ListTile(
            leading: Image.asset("assets/images/logout.png"),
            title: const Text(
              'Log out',
              style: TextStyle(
                color: Colors.black,
                fontSize: 14.0,
                fontWeight: FontWeight.normal,
              ),
            ),
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => const LoginScreen()),
              );
            },
          ),
          const Divider(color: Colors.black, height: 10, thickness: 1),
        ],
      ),
    );
  }
}

方案二:用StatefulBuilder局部管理Dropdown状态

如果不想修改整个组件的类型,可通过StatefulBuilder为Dropdown创建局部状态:

修改DrawerHeader部分的代码即可:

DrawerHeader(
  decoration: BoxDecoration(
      border: Border.all(color: Colors.white),
      image: const DecorationImage(
        image: AssetImage("assets/images/logo.png"),
      )),
  child: Column(
    mainAxisAlignment: MainAxisAlignment.end,
    children: [
      const Text(
        "Example@hotmail.com",
        style: TextStyle(
          color: Colors.black,
          fontSize: 14.0,
          fontWeight: FontWeight.normal,
        ),
      ),
      const SizedBox(height: 10),
      // 用StatefulBuilder包裹Dropdown,提供局部setState
      StatefulBuilder(
        builder: (context, setState) {
          List<String> itemsList = ['1', '2'];
          String? selectedItem = '1';
          return Container(
            padding: const EdgeInsets.symmetric(horizontal: 25.0, vertical: 0.0),
            child: SizedBox(
              height: 40,
              child: DropdownButtonFormField<String>(
                  decoration: const InputDecoration(
                      enabledBorder: OutlineInputBorder(
                          borderSide: BorderSide(
                    width: 1,
                    color: Colors.grey,
                  ))),
                  value: selectedItem,
                  items: itemsList
                      .map((item) => DropdownMenuItem(
                            value: item,
                            child: Text(item),
                          ))
                      .toList(),
                  onChanged: (item) => setState(() => selectedItem = item)),
            ),
          );
        },
      ),
    ],
  ),
),

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 14:50:23