Как реализовать слайдер в AlertDialog во Flutter?

Я изучаю разработку приложений на Flutter и не могу заставить свой слайдер работать в AlertDialog. Это не изменит его значения. Я поискал проблему и наткнулся на этот пост на StackOverFlow:
Flutter - Почему слайдер не обновляется в AlertDialog?
Я прочитал и вроде как понял. В принятом отвечать сказано, что:

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) {...}

Я понимаю, что мне нужно будет использовать async, await и Future. Но я не могу понять, как именно. Я потратил на эту проблему больше часа и больше не могу. Пожалуйста, простите меня, если этот вопрос глупый и глупый. Но поверьте, я старался изо всех сил.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
0
5 661
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вот минимальный работоспособный пример. Ключевые моменты:

  • Диалог представляет собой виджет с отслеживанием состояния, который сохраняет текущее значение в своем 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'),
        )
      ],
    );
  }
}

Это именно то, что я искал. Огромное спасибо! Вы вернули мне уверенность, прося помощи в stackoverflow. Будьте здоровы!

Ralph Dias 03.01.2019 10:28

просто нужно деформировать AlertDialog () с помощью StatefulBuilder ()

На вопрос был дан ответ, ответ был одобрен и принят пользователем, который спросил, даже поблагодарил за ответ в комментарии. Обычно подобные вопросы не требуют дополнительных ответов.

Peter Koltai 31.07.2021 19:36

Другие вопросы по теме