选择项目时,颤振不更新放置在对话框中的 DropdownButton

Posted

技术标签:

【中文标题】选择项目时,颤振不更新放置在对话框中的 DropdownButton【英文标题】:Flutter not updating DropdownButton placed within a dialog when item is selected 【发布时间】:2020-11-10 10:49:57 【问题描述】:

我有一个包含 DropdownButton 小部件的 alertDialog。每当我单击下拉菜单中的选项时,我希望它显示所选值。我列出了下面的代码以及 2 个屏幕截图。

我相信这可能是 Flutter 构建小部件的方式的问题,因为当我将 DropdownButton 小部件放在对话框之外时它可以工作,但是将它放在 alertDialog 中会导致它失败。我还注意到,如果我单击 DropdownButton 中的一个选项,然后退出并再次单击对话框,则所选项目会发生变化。但是,我希望更改选定的值,而无需用户点击对话框然后重新进入。

^

上图是用户第一次点击时的对话框。起初,唯一选择的项目是“我无法提供帮助”。每当用户单击 DropdownMenu 小部件并选择不同的选项(例如“其他”)时,此值都应更改。

^

这些是用户可以在下拉菜单中单击的各种选项。当用户点击它时,菜单应相应更新。

代码:

请注意,我已将 _chosenValue 定义为构建函数之外的全局变量。

void _showDecline() 

      showDialog(
        context: context,
        builder: (BuildContext context) 

          return AlertDialog(
            title: new Text("Decline Appointment Request"),
            content: Container(
              height: 100,
              width: 200,
              child: Column(
                children: <Widget>[
                  new Text("Please select an option for why you declined."),
                  new DropdownButton<String>(
                    value: _chosenValue,
                    underline: Container(),
                    items: <String>['I\'m not able to help', 'Unclear description', 'Not available at set date and time', 'Other'].map((String value) 
                      return new DropdownMenuItem<String>(
                        value: value,
                        child: new Text(value, style: TextStyle(fontWeight: FontWeight.w500),),
                      );
                    ).toList(),
                     onChanged: (String value) 
                       setState(() 
                        _chosenValue = value;
                      );
                    ,
                  )
                ],
              ),
            ),
            actions: <Widget>[
              // usually buttons at the bottom of the dialog
              new FlatButton(
                child: new Text("Close"),
                onPressed: () ,
                ,
              ),
              
            ],
          );
        ,
      );
    

【问题讨论】:

这能回答你的问题吗? How to refresh an AlertDialog in Flutter? 不,我的代码中已经有一个 setState() 操作,并且对话框也放置在一个有状态的小部件中。 所以你试过了,还是不行?使用该链接发布您的最佳尝试,我们会看看有什么问题。 下面的答案都有效。 嗯,大惊喜,他们告诉你的和我 12 小时前的链接告诉你的一样。 【参考方案1】:

setState 只会更新当前 StatefulWidget 的 Widget Build 功能。

您应该在 showDialog 中使用 StatefulBuilder。

对于您的情况,只需将 StatefulBuilder 添加为 DropDown 小部件的父级,并在您想要更新 StatefulBuilder 的子级时使用 StateSetter。 它只会更新在 StateFulBuilder 构建器函数下定义的小部件树。


在 DartPad 代码StateFulBuilderDartPad 上查看包括 stateFulBuilder 在内的完整代码。

有关 StatefulBuilder 的更多信息,请访问 StateFulBuilder 文档页面。

【讨论】:

你写自己的答案,而不是投票给副本有什么原因吗? 我没有得到你在评论中提到的那个重复的问题,所以我写下我的答案 我试图解释这些事情,而不是仅仅给出代码......【参考方案2】:
import 'dart:convert';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(home: HomePage());
  


class HomePage extends StatefulWidget 
  @override
  _HomePageState createState() => _HomePageState();


class _HomePageState extends State<HomePage> 
  String _chosenValue;

  void _showDecline() 
    showDialog(
      context: context,
      builder: (BuildContext context) 
        return StatefulBuilder(
          builder: (BuildContext context, StateSetter setState) 
            return AlertDialog(
              title: new Text("Decline Appointment Request"),
              content:
                  Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
                new Text("Please select an option for why you declined."),
                SingleChildScrollView(
                    scrollDirection: Axis.horizontal,
                    child: new DropdownButton<String>(
                      hint: Text('Select one option'),
                      value: _chosenValue,
                      underline: Container(),
                      items: <String>[
                        'I\'m not able to help',
                        'Unclear description',
                        'Not available at set date and time',
                        'Other'
                      ].map((String value) 
                        return new DropdownMenuItem<String>(
                          value: value,
                          child: new Text(
                            value,
                            style: TextStyle(fontWeight: FontWeight.w500),
                          ),
                        );
                      ).toList(),
                      onChanged: (String value) 
                        setState(() 
                          _chosenValue = value;
                        );
                      ,
                    )),
              ]),
              actions: <Widget>[
                // usually buttons at the bottom of the dialog
                new FlatButton(
                  child: new Text("Close"),
                  onPressed: () 
                    Navigator.of(context).pop();
                  ,
                ),
              ],
            );
          ,
        );
      ,
    );
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: SafeArea(
        child: Container(
          child: FlatButton(child: Text('Click'), onPressed: _showDecline),
        ),
      ),
    );
  

【讨论】:

在我的回答之上,我解决了错误 RIGHT OVERFLOWED BY 68 PIXELS 。 你写自己的答案,而不是投票给副本有什么原因吗?【参考方案3】:

看看下面的例子,你必须使用 statefulBuilder 来改变状态。

import 'dart:convert';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(home: HomePage());
  


class HomePage extends StatefulWidget 
  @override
  _HomePageState createState() => _HomePageState();


class _HomePageState extends State<HomePage> 
  String _chosenValue;
 
  void _showDecline() 
    showDialog(
      context: context,
      builder: (BuildContext context) 
        return StatefulBuilder(
          builder: (BuildContext context, StateSetter setState)
            return AlertDialog(
            title: new Text("Decline Appointment Request"),
            content: Container(
              height: 100,
              width: 200,
              child: Column(
                children: <Widget>[
                  new Text("Please select an option for why you declined."),
                  new DropdownButton<String>(
                    hint: Text('Select one option'),
                    value: _chosenValue,
                    underline: Container(),
                    items: <String>[
                      'I\'m not able to help',
                      'Unclear description',
                      'Not available at set date and time',
                      'Other'
                    ].map((String value) 
                      return new DropdownMenuItem<String>(
                        value: value,
                        child: new Text(
                          value,
                          style: TextStyle(fontWeight: FontWeight.w500),
                        ),
                      );
                    ).toList(),
                    onChanged: (String value) 
                      setState(() 
                        _chosenValue = value;
                      );
                    ,
                  )
                ],
              ),
            ),
            actions: <Widget>[
              // usually buttons at the bottom of the dialog
              new FlatButton(
                child: new Text("Close"),
                onPressed: () 
                  Navigator.of(context).pop();
                ,
              ),
            ],
          );
          ,
                  
        );
      ,
    );
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: SafeArea(
              child: Container(
          child: FlatButton(child: Text('Click'), onPressed: _showDecline),
        ),
      ),
    );
  



只要让我知道它是否有效。

【讨论】:

你写自己的答案,而不是投票给副本有什么原因吗?【参考方案4】:
  onTap: () 
          ///___________________________________________________________________
          // Get.defaultDialog(
          //   title: " وضعیت دزدگیر",
          //   middleText: "پیام اعلام وضعیت دزدگیر ارسال گردد؟",
          //   titleStyle: TextStyle(
          //       color: mainColor2, fontWeight: FontWeight.bold, fontSize: 16),
          //   middleTextStyle:
          //   TextStyle(color: mainColor6.withOpacity(0.9), fontSize: 15),
          // );
          ///----------------------------------------------------------------------
          // showDialog(
          //     context: context,
          //     builder: (context) => AlertDialog(
          //       content: Column(
          //         children: <Widget>[
          //           TextField(
          //             decoration: InputDecoration(
          //               icon: Icon(Icons.account_circle),
          //               labelText: 'Username',
          //             ),
          //           ),
          //           TextField(
          //             obscureText: true,
          //             decoration: InputDecoration(
          //               icon: Icon(Icons.lock),
          //               labelText: 'Password',
          //             ),
          //           ),
          //         ],
          //       ),
          //     ),
          // );
          ///___________________________________________________________________
          List<DropdownMenuItem<String>> listDrop = [];
          String selected=null;
          void loadData() 
            listDrop.add(new DropdownMenuItem(
              child: new Text("پایدار"),
              value:"555",
            ));
            listDrop.add(
              new DropdownMenuItem(
                child: new Text("لحظه ای"),
                value:"444",
              ),
            );
          
          loadData();

          Alert(
              context: context,
              title: "تنظیمات خروجی شماره ۱",
              // desc: ".",
              // image: Image.asset(
              //   "assets/settings.png",
              //   scale: 5,
              // ),
              content: Directionality(
                textDirection: TextDirection.rtl,
                child: Center(
                  child: Column(
                    children: <Widget>[
                      SizedBox(height: 20.0),
                      TextField(
                        keyboardType: TextInputType.text,
                        controller: _codeShargController,
                        decoration: InputDecoration(
                          labelText: 'نام خروجی',
                          hintText: '$out1.read('codeShargController')',
                        ),
                      ),
                      SizedBox(height: 25.0),
                      Center(


                        child: DropdownButton(
                          underline: Container(
                            height: 1.5,
                            color: Colors.black26,
                          ),
                          hint: Text("وضعیت عملکرد"),
                          items: listDrop,
                          isExpanded: true,
                          value: selected,
                          style: TextStyle(color: Colors.black, fontSize: 16),
                          onChanged: (newValue)  
                            selected = newValue;
                           // setState(() );
                            setState(()  selected = newValue; );

                          ,
                        ),





                      ),
                      SizedBox(height: 25.0),
                    ],
                  ),
                ),
              ),
              // content: Column(
              //   children: <Widget>[
              //
              //     SizedBox(height: 10.0),
              //
              //     TextField(
              //
              //       decoration: InputDecoration(
              //
              //         icon: Icon(Icons.account_circle),
              //         labelText: 'Username',
              //       ),
              //     ),
              //     SizedBox(height: 10.0),
              //
              //     TextField(
              //       obscureText: true,
              //       decoration: InputDecoration(
              //         icon: Icon(Icons.lock),
              //         labelText: 'Password',
              //       ),
              //     ),
              //   ],
              // ),
              buttons: [
                DialogButton(
                  onPressed: () 
                    out1.write(
                        "codeShargController", _codeShargController.text);

                    Navigator.pop(context);
                  ,
                  child: Text(
                    "ثبت",
                    style: TextStyle(color: Colors.white, fontSize: 20),
                  ),
                )
              ]).show();

          ///___________________________________________________________________

【讨论】:

以上是关于选择项目时,颤振不更新放置在对话框中的 DropdownButton的主要内容,如果未能解决你的问题,请参考以下文章

颤振中的根项目

如何在颤振中实现未来的下拉列表并根据用户选择更新值

颤振选择对话框 - 将过滤器字段滚动到视图中

颤振状态不会更新

在颤振应用程序中仅选择一个复选框列表标题

旋转时,从 UITableViewCell 显示的 UIPopoverController 放置不正确