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

Firestore填充的DropdownButton选中项不显示问题求助

问题:DropdownButton选中项无法更新按钮文本

我需要DropdownButton的选中项显示为按钮文本,目前点击下拉列表中的选项后,SnackBar能正确提示选中项,但按钮文本并未更新。后续还计划通过提交按钮将选中项保存到Firestore,尚未推进到这一步。

更新:添加参考方案后出现报错。

原代码

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

class InfoScreen extends StatefulWidget {
  const InfoScreen({Key? key}) : super(key: key);

  @override
  State<InfoScreen> createState() => _InfoScreenState();
}

class _InfoScreenState extends State<InfoScreen> {
  String selectedFaction = '';
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          onPressed: () {},
          icon: const Icon(Icons.person_sharp),
        ),
        elevation: 5,
        centerTitle: true,
        titleSpacing: 0,
        title: const Text('Info Screen'),
        actions: <Widget>[
          IconButton(
            onPressed: () {},
            icon: const Icon(Icons.settings),
          ),
        ],
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(20),
        child: Center(
          child: Column(
            children: [
              StreamBuilder<QuerySnapshot>(
                stream: FirebaseFirestore.instance
                    .collection("factions")
                    .snapshots(),
                builder: (BuildContext context,
                    AsyncSnapshot<QuerySnapshot> snapshot) {
                  if (snapshot.hasData) {
                    final factionDatabaseSnapshot = snapshot.data!.docs;
                    factionDatabaseSnapshot.sort(
                      ((a, b) {
                        return a['name']
                            .toLowerCase()
                            .compareTo(b['name'].toLowerCase());
                      }),
                    );
                    return DropdownButton(
                      onChanged: (snap) {
                        setState(() {
                          selectedFaction = snap.toString();
                        });
                        final snackbarFaction = SnackBar(
                          content: Text('Faction Selected: $selectedFaction'),
                        );
                        ScaffoldMessenger.of(context)
                            .showSnackBar(snackbarFaction);
                      },
                      items: factionDatabaseSnapshot
                          .map((DocumentSnapshot document) {
                        return DropdownMenuItem<String>(
                          value: document['name'],
                          child: Text(document['name']),
                        );
                      }).toList(),
                      isExpanded: false,
                      isDense: false,
                      hint: const Text('Select a faction'),
                    );
                  } else {
                    return const CircularProgressIndicator();
                  }
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}

解决方案

问题根源:

  1. DropdownButton未绑定value属性,无法感知选中状态变化,导致按钮文本不更新
  2. onChanged中错误调用snap.toString(),会把String类型的选中值转为Instance of 'String'这类无效内容

修改步骤:

  • 给DropdownButton添加value属性,绑定selectedFaction,让按钮自动同步选中值
  • 直接将snap赋值给selectedFaction(无需toString())
  • 可选:初始化时自动选中第一个选项,避免初始空值的异常

修改后的完整代码

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

class InfoScreen extends StatefulWidget {
  const InfoScreen({Key? key}) : super(key: key);

  @override
  State<InfoScreen> createState() => _InfoScreenState();
}

class _InfoScreenState extends State<InfoScreen> {
  String selectedFaction = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          onPressed: () {},
          icon: const Icon(Icons.person_sharp),
        ),
        elevation: 5,
        centerTitle: true,
        titleSpacing: 0,
        title: const Text('Info Screen'),
        actions: <Widget>[
          IconButton(
            onPressed: () {},
            icon: const Icon(Icons.settings),
          ),
        ],
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(20),
        child: Center(
          child: Column(
            children: [
              StreamBuilder<QuerySnapshot>(
                stream: FirebaseFirestore.instance.collection("factions").snapshots(),
                builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
                  if (snapshot.hasData) {
                    final factionDatabaseSnapshot = snapshot.data!.docs;
                    factionDatabaseSnapshot.sort(
                      ((a, b) {
                        return a['name'].toLowerCase().compareTo(b['name'].toLowerCase());
                      }),
                    );
                    // 初始化自动选中第一个选项(可选)
                    if (selectedFaction.isEmpty && factionDatabaseSnapshot.isNotEmpty) {
                      WidgetsBinding.instance.addPostFrameCallback((_) {
                        setState(() {
                          selectedFaction = factionDatabaseSnapshot.first['name'];
                        });
                      });
                    }
                    return DropdownButton<String>(
                      // 绑定选中值,空值时显示hint
                      value: selectedFaction.isEmpty ? null : selectedFaction,
                      onChanged: (snap) {
                        if (snap == null) return;
                        setState(() {
                          selectedFaction = snap;
                        });
                        final snackbarFaction = SnackBar(
                          content: Text('Faction Selected: $selectedFaction'),
                        );
                        ScaffoldMessenger.of(context).showSnackBar(snackbarFaction);
                      },
                      items: factionDatabaseSnapshot.map((DocumentSnapshot document) {
                        return DropdownMenuItem<String>(
                          value: document['name'],
                          child: Text(document['name']),
                        );
                      }).toList(),
                      isExpanded: false,
                      isDense: false,
                      hint: const Text('Select a faction'),
                    );
                  } else {
                    return const CircularProgressIndicator();
                  }
                },
              ),
              // 后续可添加的保存按钮示例
              // ElevatedButton(
              //   onPressed: () {
              //     if (selectedFaction.isNotEmpty) {
              //       FirebaseFirestore.instance.collection('user_data').add({
              //         'selected_faction': selectedFaction,
              //         'timestamp': FieldValue.serverTimestamp(),
              //       });
              //       ScaffoldMessenger.of(context).showSnackBar(
              //         const SnackBar(content: Text('选中项已保存')),
              //       );
              //     }
              //   },
              //   child: const Text('保存选中项'),
              // )
            ],
          ),
        ),
      ),
    );
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 18:45:41