Динамический список плитки флажка в диалоговом окне предупреждения не работает - PullRequest
0 голосов
/ 10 сентября 2018

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

Оператор печати работает, при этом состояние флажка не меняется, но работают другие операторы. Где я могу найти ответ?

Я использую диалог с несколькими флажками для множественного выбора. Есть ли еще один способ реализации множественного выбора во Flutter?

   child: TextFormField(
     decoration: InputDecoration(
         labelText: 'Team Leader',
         labelStyle: TextStyle(color: Colors.black)),
     controller: teamLeaderController,
     enabled: false,
     style: TextStyle(color: Colors.black),
   ),
   onTap: () {
     showDialog(
         context: context,
         barrierDismissible: true,
         builder: (BuildContext context) {
           return CheckBoxDialog(context, teamLeader,
               "Choose Team Leader", teamLeaderController, onSubmit);
         });
   }),

class CheckBoxState extends State<CheckBoxDialog> {
  BuildContext context;
  List<String> places;
  String title;
  TextEditingController con;
  bool state;
  CheckBoxState(this.context, this.places, this.title, this.con);

  @override
  void initState() {
    super.initState();
    state = false;
  }

  @override
  Widget build(BuildContext context) {
    return new AlertDialog(
      title: new Text(title),
      content:
          Column(children: getMultiSelectOption(context, places, con, state)),
      actions: <Widget>[
        FlatButton(
            child: Text('Cancel'),
            onPressed: () {
              Navigator.of(context).pop();
            }),
        FlatButton(
            child: Text('Ok'),
            onPressed: () {
              widget.onSubmit("");
              Navigator.of(context).pop();
            })
      ],
    );
  }

  List<Widget> getMultiSelectOption(BuildContext context, List<String> places,
      TextEditingController con, bool state) {
    List<Widget> options = [];
    List<String> selectedList = [];
    for (int i = 0; i < places.length; i++) {
      options.add(CheckboxListTile(
          title: Text(places[i]),
          value: selectedList.contains(places[i]),
          onChanged: (bool value) {
            print("on change: $value  title: ${places[i]}");
            setState(() {
              if (value) {
                selectedList.add(places[i]);
              } else {
                selectedList.remove(places[i]);
              }
              print("contains: ${selectedList.contains(places[i])}");
              print("status: $value");
            });
          }));
    }
    return options;
  }
}

1 Ответ

0 голосов
/ 26 марта 2019

Предположим, у вас есть диалог с некоторыми виджетами, такими как RadioListTile, DropdowButton ... или что-то, что может потребоваться обновить, пока диалог остается видимым, как это сделать?

Посмотрите на этот пример здесь. https://www.didierboelens.com/2018/05/hint-5-how-to-refresh-the-content-of-a-dialog-via-setstate/

Предположим, у вас есть диалог с некоторыми виджетами, такими как RadioListTile, DropdowButton ... или что-то, что может потребоваться обновить, пока диалог остается видимым, как это сделать?

Сложность: начинающий

Фоновая В последнее время мне приходилось отображать диалог, чтобы позволить пользователю выбрать элемент из списка, и я хотел отобразить список RadioListTile.

У меня не было проблем с отображением диалога и отображением списка через следующий исходный код:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

class Sample extends StatefulWidget {
  @override
  _SampleState createState() => new _SampleState();
}

class _SampleState extends State<Sample> {
  List<String> countries = <String>['Belgium','France','Italy','Germany','Spain','Portugal'];
  int _selectedCountryIndex = 0;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_){_showDialog();});
  }

  _buildList(){
    if (countries.length == 0){
      return new Container();
    }

    return new Column(
      children: new List<RadioListTile<int>>.generate(
        countries.length,
        (int index){
          return new RadioListTile<int>(
            value: index,
            groupValue: _selectedCountryIndex,
            title: new Text(countries[index]),
            onChanged: (int value) {
              setState((){
                _selectedCountryIndex = value;
              });
            },
          );
        }
      )
    );
  }

  _showDialog() async{
    await showDialog<String>(
      context: context,
      builder: (BuildContext context){
        return new CupertinoAlertDialog(
          title: new Text('Please select'),
          actions: <Widget>[
            new CupertinoDialogAction(
              isDestructiveAction: true,
              onPressed: (){Navigator.of(context).pop('Cancel');},
              child: new Text('Cancel'),
            ),
            new CupertinoDialogAction(
              isDestructiveAction: true,
              onPressed: (){Navigator.of(context).pop('Accept');},
              child: new Text('Accept'),
            ),
          ],
          content: new SingleChildScrollView(
            child: new Material(
              child: _buildList(),
            ),
          ),
        );
      },
      barrierDismissible: false,
    );
  }

  @override
  Widget build(BuildContext context) {
    return new Container();
  }
}

Я был удивлен, увидев, что несмотря на setState в строках # 34-36, выбранный RadioListTile не обновлялся, когда пользователь касался одного из элементов.

Пояснение После некоторого исследования я понял, что setState () ссылается на виджет с состоянием, в котором вызывается setState. В этом примере любой вызов setState () перестраивает представление Sample Widget, а не содержимое диалога. Поэтому как это сделать?

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

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

class Sample extends StatefulWidget {
  @override
  _SampleState createState() => new _SampleState();
}

class _SampleState extends State<Sample> {
  List<String> countries = <String>['Belgium','France','Italy','Germany','Spain','Portugal'];

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_){_showDialog();});
  }

  _showDialog() async{
    await showDialog<String>(
      context: context,
      builder: (BuildContext context){
        return new CupertinoAlertDialog(
          title: new Text('Please select'),
          actions: <Widget>[
            new CupertinoDialogAction(
              isDestructiveAction: true,
              onPressed: (){Navigator.of(context).pop('Cancel');},
              child: new Text('Cancel'),
            ),
            new CupertinoDialogAction(
              isDestructiveAction: true,
              onPressed: (){Navigator.of(context).pop('Accept');},
              child: new Text('Accept'),
            ),
          ],
          content: new SingleChildScrollView(
            child: new Material(
              child: new MyDialogContent(countries: countries),
            ),
          ),
        );
      },
      barrierDismissible: false,
    );
  }

  @override
  Widget build(BuildContext context) {
    return new Container();
  }
}

class MyDialogContent extends StatefulWidget {
  MyDialogContent({
    Key key,
    this.countries,
  }): super(key: key);

  final List<String> countries;

  @override
  _MyDialogContentState createState() => new _MyDialogContentState();
}

class _MyDialogContentState extends State<MyDialogContent> {
  int _selectedIndex = 0;

  @override
  void initState(){
    super.initState();
  }

  _getContent(){
    if (widget.countries.length == 0){
      return new Container();
    }

    return new Column(
      children: new List<RadioListTile<int>>.generate(
        widget.countries.length,
        (int index){
          return new RadioListTile<int>(
            value: index,
            groupValue: _selectedIndex,
            title: new Text(widget.countries[index]),
            onChanged: (int value) {
              setState((){
                _selectedIndex = value;
              });
            },
          );
        }
      )
    );
  }

  @override
  Widget build(BuildContext context) {
    return _getContent();
  }
}
...