在屏幕之间传递数据,但使用提取的下拉按钮小部件

时间:2020-07-11 20:52:26

标签: flutter screen navigator

首先,这是我的病情。我试图将第一个屏幕(左图)的Dropdownbutton和Date&Time选择器中填充的所有数据传递到第二个屏幕(右图)。问题是,我将DropDownButton小部件提取到另一个类,但我不知道如何实现它。

First screen Second Screen

在此之前,这是第一个屏幕代码:

    "cleanUrls": true,
    "trailingSlash": false,

在第一张图片下方,有一个按钮导航到第二张屏幕。

这是我提取DropDownButton的类:

  class InformationDetail extends StatefulWidget {
  static const String id = 'InformationDetail';
  @override
  _InformationDetailState createState() => _InformationDetailState();
}

class _InformationDetailState extends State<InformationDetail> {
  String addressText, addNotes;
  DateTime selectedDate = DateTime.now();
  TimeOfDay selectedTime = TimeOfDay.now();

  Future<Null> _selectDate(BuildContext context) async {
    final DateTime picked = await showDatePicker(
        context: context,
        initialDate: selectedDate,
        firstDate: DateTime(2015, 8),
        lastDate: DateTime(2101));
    if (picked != null && picked != selectedDate)
      setState(() {
        selectedDate = picked;
      });
  }

  Future<Null> _selectTime(BuildContext context) async {
    final TimeOfDay picked = await showTimePicker(
      context: context,
      initialTime: selectedTime,
    );
    if (picked != null && picked != selectedTime)
      setState(() {
        selectedTime = picked;
      });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
          child: ListView(
        children: <Widget>[
          Container(
            child: Column(
              children: <Widget>[
                Container(
                  margin: EdgeInsets.fromLTRB(25.0, 68.0, 70.0, 26.0),
                  child: Text(
                    'Information Detail',
                    style: TextStyle(fontSize: 35.0),
                  ),
                ),
                Column(
                  // Wrap Column
                  children: <Widget>[
                    Column(
                      children: <Widget>[
                        TitleName(
                          titleText: 'Grooming Type',
                          infoIcon: Icons.info,
                        ),
                        MenuDropDown(
                          dropdownText: 'Grooming Type...',
                          type: "groomingType",
                        ),
                        TitleName(
                          titleText: 'Cat Breeds',
                        ),
                        MenuDropDown(
                          dropdownText: 'Cat Breeds...',
                          type: "catBreeds",
                        ),
                        TitleName(
                          titleText: 'Cat Size',
                          infoIcon: Icons.info,
                        ),
                        MenuDropDown(
                          dropdownText: 'Cat Size...',
                          type: "catSize",
                        ),
                        TitleName(
                          titleText: 'Add-On Services',
                        ),
                        MenuDropDown(
                          dropdownText: 'Add - On Services...',
                          type: "addOnServices",
                        ),
                        TitleName(
                          titleText: 'Reservation Date',
                        ),
                        Row(
                          children: <Widget>[
                            Container(
                              width: 130,
                              height: 30,
                              margin: EdgeInsets.fromLTRB(50.0, 0, 62, 0),
                              child: RaisedButton(
                                color: Colors.white,
                                shape: RoundedRectangleBorder(
                                  borderRadius: BorderRadius.circular(15.0),
                                ),
                                elevation: 6,
                                child: Text(
                                  'Choose Date',
                                  style: TextStyle(
                                    fontSize: 12.0,
                                  ),
                                ),
                                onPressed: () => _selectDate(context),
                              ),
                            ),
                            Text("${selectedDate.toLocal()}".split(' ')[0]),
                          ],
                        ),
                        TitleName(
                          titleText: 'Reservation Time',
                        ),
                        Row(
                          children: <Widget>[
                            Container(
                              width: 130,
                              height: 30,
                              margin: EdgeInsets.fromLTRB(50.0, 0, 62, 0),
                              decoration: BoxDecoration(),
                              child: RaisedButton(
                                color: Colors.white,
                                child: Text(
                                  'Choose Time',
                                  style: TextStyle(
                                    fontSize: 12.0,
                                  ),
                                ),
                                shape: RoundedRectangleBorder(
                                  borderRadius: BorderRadius.circular(15.0),
                                ),
                                elevation: 6,
                                onPressed: () => _selectTime(context),
                              ),
                            ),
                            Text("${selectedTime.toString()}".split(' ')[0]),
                          ],
                        ),
                        TitleName(
                          titleText: 'Pick Up Address',
                        ),
                        Container(
                          width: 320,
                          height: 40,
                          child: TextFormField(
                            maxLines: null,
                            minLines: null,
                            expands: true,
                            decoration: InputDecoration(
                              contentPadding:
                                  EdgeInsets.fromLTRB(35.0, 10.0, 0, 10.0),
                              hintText: 'Address Here...',
                              hintStyle: TextStyle(
                                fontSize: 15.0,
                              ),
                              border: OutlineInputBorder(
                                borderRadius: BorderRadius.circular(15.0),
                              ),
                            ),
                            onChanged: (value) {
                              addressText = value;
                            },
                          ),
                        ),
                        TitleName(
                          titleText: 'Additional Notes',
                          infoIcon: Icons.info,
                        ),
                        Container(
                          width: 320,
                          child: TextFormField(
                            maxLines: 4,
                            decoration: InputDecoration(
                              contentPadding:
                                  EdgeInsets.fromLTRB(35.0, 10.0, 0, 10.0),
                              hintText: 'E.g. ',
                              hintStyle: TextStyle(
                                fontSize: 15.0,
                              ),
                              border: OutlineInputBorder(
                                borderRadius: BorderRadius.circular(15.0),
                              ),
                            ),
                            onChanged: (value) {
                              addNotes = value;
                            },
                          ),
                        ),
                        Container(
                          margin: EdgeInsets.fromLTRB(0, 15.0, 0, 0),
                          width: 75.0,
                          decoration: BoxDecoration(
                            color: Colors.white,
                            shape: BoxShape.rectangle,
                            border: Border.all(
                              color: Colors.black,
                            ),
                            borderRadius: BorderRadius.circular(12.0),
                          ),
                          child: IconButton(
                              icon: Icon(Icons.arrow_forward),
                              onPressed: () {
                                Navigator.of(context).push(MaterialPageRoute(
                                    builder: (context) => ConfirmationOrder(
                                          addressText: addressText,
                                          addNotes: addNotes,
                                        )));
                              }),
                        ),
                      ],
                    ),
                  ],
                ),
              ],
            ),
          ),
        ],
      )),
    );
  }
}

我真的很困惑,因为DropDownButton中的onChanged函数已经被使用了。我几乎无法从文本窗口小部件中进行正常的传递数据。但是从下拉菜单和日期和时间选择器中,我不知道该怎么做。

有什么方法可以从第一个屏幕上获取数据,因为目前我还没有了解状态管理或Bloc。而且代码仍然凌乱,我还没有完成重构。我真的希望您能提供解决方案,谢谢!

1 个答案:

答案 0 :(得分:1)

首先,对于MenuDropDown,您将需要对onChanged方法进行某种扩展。像这样向小部件的构造函数添加一个VoidCallback参数:

typedef OnChangeCallback = void Function(dynamic value);

class MenuDropDown extends StatefulWidget {
  final String dropdownText;
  final String type;
  final OnChangeCallback onChanged;

  MenuDropDown({this.dropdownText, this.type, this.onChanged});

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

并在状态下,将该方法作为DropdownButton的本机onChanged回调的一部分进行调用:

onChanged: (value) {
  setState(() {
    selectedItem = value;
  });
  widget.onChanged(value);
}

_InformationDetailState中,您将为每个输入字段存储当前选定的项目,并传递一个onChanged函数,该函数将为每个输入更新相应的字段:

String catSize; //Declare at the top of _InformationDetailState
...
MenuDropDown(
  dropdownText: 'Cat Size...',
  type: "catSize",
  onChanged: (value) {
    catSize = value;
  }
),

现在将数据传递到下一个屏幕。在您的应用程序中使用任何一种状态管理从来都不是绝对必要的,而且我发现很多人不必要地使用它。在您的情况下,仅将数据传递到其他单个小部件绝对没有必要。您已经正确传递了addressTextaddNotes。只需将其扩展为您需要在确认屏幕上显示的每个参数即可。或者,您可以将所有字段存储在单个Map中,而不是每个字段都有一个变量,然后将该Map传递到确认页面。