Flutter - 为什么 AlertDialog 中的滑块不更新?

问题描述 投票:0回答:6

我做了一个AlertDialog,所以当我尝试在值状态中插入Slider小部件时,听起来真的很奇怪,如果Slider位于AlertDialog之外,则不会发生这种情况

new Slider(
  onChanged: (double value) {
    setState(() {
      sliderValue = value;
    });
  },
  label: 'Oi',
  divisions: 10,
  min: 0.0,
  max: 10.0,
  value: sliderValue,
)

AlertDialog完整的widget代码

Future<Null> _showDialog() async {
  await showDialog<Null>(
      context: context,
      builder: (BuildContext context) {
        return new AlertDialog(
          title: const Text('Criar novo cartão'),
          actions: <Widget>[
            new FlatButton(onPressed: () {
              Navigator.of(context).pop(null);
            }, child: new Text('Hello'))
          ],
          content: new Container(
            child: new Column(
              mainAxisAlignment: MainAxisAlignment.start,
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                new Text('Deseja iniciar um novo cartão com quantos pedidos ja marcados?'),
                new Slider(
              onChanged: (double value) {
                setState(() {
                  sliderValue = value;
                });
              },
              label: 'Oi',
              divisions: 10,
              min: 0.0,
              max: 10.0,
              value: sliderValue,
            )
              ],
            ),
          ),
        );
      }
  );
}

一切都在 StatefullWidget 的 State 类下。

它看起来不会更新值,并且当尝试更改值时保持在相同位置。

更新1

问题是 Slider 中有 2 个必需参数

(onChanged, value)
,所以我应该更新这个或 UI 保持安静,看看应用程序如何运行的视频

Youtube 上的视频

更新2

我还在 Github 存储库中打开了一个问题以获取有关此问题的帮助,如果有人想获取更多信息可以转到 issue #19323

dart flutter flutter-layout
6个回答
14
投票

问题在于,保存状态的不是您的对话框。这是名为

showDialog
的小部件。当您调用
setState
时也是如此,您正在调用对话框创建者。

问题是,对话框不是内置于

build
方法中。它们位于不同的小部件树上。因此,当对话框创建器更新时,对话框不会更新。

相反,您应该使对话框有状态。将数据保存在该对话框中。然后使用

Navigator.pop(context, sliderValue)
将滑块值发送回对话框创建者。

对话框中的等效内容是

FlatButton(
  onPressed: () => Navigator.of(context).pop(sliderValue),
  child: Text("Hello"),
)

然后您可以在

showDialog
结果中捕获它:

final sliderValue = await showDialog<double>(
  context: context,
  builder: (context) => MyDialog(),
)

6
投票

最简单且最少的线路: 使用 StatefulBuilder 作为 AlertDialog 中内容的顶部小部件。

                StatefulBuilder(
                  builder: (context, state) => CupertinoSlider(
                    value: brightness,
                    onChanged: (val) {
                      state(() {
                        brightness = val;
                      });
                    },
                  ),
                ));

5
投票

我在复选框中遇到了同样的问题,这就是我的解决方案,即使这不是最好的方法。 (见代码中的注释)

Future<Null>_showDialog() async {
  return showDialog < Null > (
    context: context,
    barrierDismissible: true,
    builder: (BuildContext context) {
      return new AlertDialog(
        title: Text("title"),
        content: Container(
          height: 150.0,
          child: Checkbox(
            value: globalSearch,
            onChanged: (bool b) {
              print(b);
              globalSearch = b;
              Navigator.of(context).pop(); // here I pop to avoid multiple Dialogs
              _showDialog(); //here i call the same function
            },
          )),
      );
    },
  );
}

3
投票

我遇到了类似的问题,并通过将 AlertDialog 下的所有内容放入 StatefullWidget 中来解决。

    class <your dialog widget> extends StatefulWidget {
  @override
  _FilterDialogState createState() => _FilterDialogState();
}

class _<your dialog widget> extends State<FilterDialog> {

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      //your alert dialog content here
    );
  }
}

0
投票

在返回时使用滑块创建一个有状态类,并且双精度值应在有状态类内声明,因此 setstate 函数将起作用。

这是我为滑块弹出窗口执行此操作的示例,它与警报对话框相同,可以将变量声明为全局变量,因此可以由其他类访问它

    class _PopupMenuState extends State<PopupMenu> {
      double _fontSize=15.0;
    
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Slider(
            value: _fontSize,
            min: 10,
            max: 100,
            onChanged: (value) {
              setState(() {
                print(value);
                _fontSize = value;
              });
            },
          ),
        );
      }
    }

0
投票

我面临这个问题,并且发现上述所有解决方案都对我没有帮助,所以我尝试解决它并且成功了 这是我的解决方案:

import 'package:flutter/material.dart';

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

  @override
  State<PopUpWidget> createState() => _PopUpWidgetState();
}

class _PopUpWidgetState extends State<PopUpWidget> {
  List<String> img = [
    'assets/images/formImage/team_effort.png',
    'assets/images/formImage/playing_golf.png',
    'assets/images/formImage/phone.png',
    'assets/images/formImage/confirm.png'
  ];
  int value = 0;
  @override
  Widget build(BuildContext context) {
    return Container(
        child: StatefulBuilder(
      builder: (context, state) => AlertDialog(
        content: Wrap(
          children: [
            Column(
              children: [
                Container(
                  alignment: Alignment.topRight,
                  child: CloseButton(
                    color: Colors.black,
                    onPressed: () {
                      Navigator.pop(context, '');
                    },
                  ),
                ),
                Container(
                    child: Row(
                  children: [
                    Expanded(
                      flex: 1,
                      child: TextButton(
                          onPressed: () {
                            setState(() {
                              if (value > 0) {
                                value = value - 1;
                              }
                            });
                          },
                          child: Icon(Icons.arrow_back)),
                    ),
                    Expanded(
                      child: Image.asset(img[value]),
                      flex: 2,
                    ),
                    Expanded(
                      flex: 1,
                      child: TextButton(
                          onPressed: () {
                            setState(() {
                              if (value < 3) {
                                value = value + 1;
                              }
                            });
                          },
                          child: Icon(Icons.arrow_forward)),
                    ),
                  ],
                ))
              ],
            ),
          ],
        ),
        surfaceTintColor: Colors.transparent,
        backgroundColor: Colors.transparent,
      ),
    ));
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.