flutter - 如何在 Flutter 的 AlertDialog 中实现 Slider?

标签 flutter slider android-alertdialog

我正在学习 Flutter 上的应用程序开发,但无法让我的 Slider 在 AlertDialog 中工作。它不会改变它的值(value)。
我确实搜索了这个问题并在 StackOverFlow 上看到了这篇文章:
Flutter - Why slider doesn't update in AlertDialog?
我读了它并且有点理解它。接受answer说:

The problem is, dialogs are not built inside build method. They are on a different widget tree. So when the dialog creator updates, the dialog won't.

但是,由于没有提供足够的后台代码,我无法理解它到底是如何实现的。

这是我当前的实现方式:

double _fontSize = 1.0;

@override
Widget build(BuildContext context) {
  return Scaffold(
      appBar: AppBar(
        title: Text(qt.title),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.format_size),
            onPressed: () {
              getFontSize(context);
            },
          ),
        ],
      ),
      body: ListView.builder(
          padding: EdgeInsets.symmetric(vertical: 15.0),
          itemCount: 3,
          itemBuilder: (context, index) {
            if (index == 0) {
              return _getListTile(qt.scripture, qt.reading);
            } else if (index == 1) {
              return _getListTile('Reflection:', qt.reflection);
            } else {
              return _getListTile('Prayer:', qt.prayer);
            }
          })
  );
}

void getFontSize(BuildContext context) {
  showDialog(context: context,builder: (context){
    return AlertDialog(
      title: Text("Font Size"),
      content: Slider(
        value: _fontSize,
        min: 0,
        max: 100,
        divisions: 5,
        onChanged: (value){
          setState(() {
            _fontSize = value;
          });
        },
      ),
      actions: <Widget>[
        RaisedButton(
          child: Text("Done"),
          onPressed: (){},
        )
      ],
    );
  });
}


Widget parseLargeText(String text) {...}

Widget _getListTile(String title, String subtitle) {...}

我知道我需要使用异步、等待和 Future。但我无法理解到底是怎么回事。我已经在这个问题上花了一个多小时,不能再多了。如果这个问题很愚蠢和菜鸟,请原谅我。但是相信我,我尽力了。

最佳答案

这是一个最小的可运行示例。要点:

  • 对话框是一个有状态的小部件,它将当前值存储在其 State 中。这很重要,因为对话框在技术上是您应用程序中独立的“页面”,插入到层次结构的较高位置
  • Navigator.pop(...) 关闭对话框并返回结果
  • 使用async/await

import 'package:flutter/material.dart';

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

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

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

class _HomePageState extends State<HomePage> {
  double _fontSize = 20.0;

  void _showFontSizePickerDialog() async {
    // <-- note the async keyword here

    // this will contain the result from Navigator.pop(context, result)
    final selectedFontSize = await showDialog<double>(
      context: context,
      builder: (context) => FontSizePickerDialog(initialFontSize: _fontSize),
    );

    // execution of this code continues when the dialog was closed (popped)

    // note that the result can also be null, so check it
    // (back button or pressed outside of the dialog)
    if (selectedFontSize != null) {
      setState(() {
        _fontSize = selectedFontSize;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Text('Font Size: ${_fontSize}'),
            RaisedButton(
              onPressed: _showFontSizePickerDialog,
              child: Text('Select Font Size'),
            )
          ],
        ),
      ),
    );
  }
}

// move the dialog into it's own stateful widget.
// It's completely independent from your page
// this is good practice
class FontSizePickerDialog extends StatefulWidget {
  /// initial selection for the slider
  final double initialFontSize;

  const FontSizePickerDialog({Key key, this.initialFontSize}) : super(key: key);

  @override
  _FontSizePickerDialogState createState() => _FontSizePickerDialogState();
}

class _FontSizePickerDialogState extends State<FontSizePickerDialog> {
  /// current selection of the slider
  double _fontSize;

  @override
  void initState() {
    super.initState();
    _fontSize = widget.initialFontSize;
  }

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: Text('Font Size'),
      content: Container(
        child: Slider(
          value: _fontSize,
          min: 10,
          max: 100,
          divisions: 9,
          onChanged: (value) {
            setState(() {
              _fontSize = value;
            });
          },
        ),
      ),
      actions: <Widget>[
        FlatButton(
          onPressed: () {
            // Use the second argument of Navigator.pop(...) to pass
            // back a result to the page that opened the dialog
            Navigator.pop(context, _fontSize);
          },
          child: Text('DONE'),
        )
      ],
    );
  }
}

关于flutter - 如何在 Flutter 的 AlertDialog 中实现 Slider?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54010876/

相关文章:

javascript - jquery 句柄和轨道样式

javascript - 如何使用jQuery创建左右滑动效果?

android - 如何检查 AlertDialog 是否被销毁

flutter - 错误组织-dartlang-调试 :synthetic_debug_expression when execute a Flutter app

dart - 从 Flutter/Dart 中的 Assets 文件夹加载文件

javascript - 添加“下一个”和“上一个”按钮以重置 Jquery 图像 slider 上的计时器

android - 如何在后台服务中使用alertDialog

android - 具有圆角和透明背景的自定义警报对话框

dart - flutter : How to specify a device id in flutter?

flutter 肘 : good way to get stored variable?