从 Flutter 中的有状态小部件返回数据

Ast*_*yne 6 widget flutter

我之前已经发布了关于这个我仍然面临的问题 哪个是将数据从有状态小部件返回到无状态小部件

我使用的小部件是 DateTimePickerFormField 小部件,我将它用作有状态小部件中的子部件

所以我查看了https://flutter.io/docs/cookbook/navigation/returning-data#complete-example

用于从小部件返回数据。但是,返回数据的小部件是无状态小部件......在我的情况下不是

所以代码如下

Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Add a Reminder'),

      ),
      body:
      new Container(
        padding: new EdgeInsets.all(20.0),
        child: new Form(
            child: new ListView(
              children: <Widget>[

            new TextFormField(
            keyboardType: TextInputType.text,
              // Use email input type for emails.
              decoration: new InputDecoration(
                hintText: 'Title of reminder',
              ),

            ),
            dateAndTimeWidget(context),
            RaisedButton(
            child: Text('Save'),
        onPressed: () {
          Navigator.pop(context);
        },
      )
      ],
    ),)
    ,
    )
    ,
    );

  }
Run Code Online (Sandbox Code Playgroud)

该小部件正在调用方法:dateAndTimeWidget,它应该返回 dateTime 有状态小部件并将输出数据保存在变量中:

 dateAndTimeWidget(BuildContext context) async {
    final result = await Navigator.push(
      context,
      MaterialPageRoute(builder: (context)=> dateTime()),
    );

}
Run Code Online (Sandbox Code Playgroud)

那么这是 dateTime Statful 小部件

class dateTime extends StatefulWidget{
    @override
  dateTimeState createState() => dateTimeState();

}
class dateTimeState extends State<dateTime>{

  static DateTime dateT;

  InputType inputType = InputType.both;

  final formats = {
    InputType.both: DateFormat("EEEE, MMMM d, yyyy 'at' h:mma"),
    InputType.date: DateFormat('yyyy-MM-dd'),
    InputType.time: DateFormat("HH:mm"),
  };

  Widget build(BuildContext context) => Container(
      child: DateTimePickerFormField(
        inputType: InputType.both,
        editable: true,
        format: formats[inputType],
        decoration: InputDecoration(
            labelText: 'Date/Time', hasFloatingPlaceholder: false),
        onChanged: (dt) {
          setState(() => dateT = dt);
          Navigator.of(context).pop(dateT);
        },

      )


  );


}
Run Code Online (Sandbox Code Playgroud)

我还没有使用值结果因为错误是我永远不会进入添加提醒页面,它说结果推送导航方法指向null

Hea*_*OSK 14

在这种情况下,不适合使用 Navigator 传递数据。因为页面和您的dateTimeWidget之间没有页面转换。我建议您实现ValueChanged回调以在同一屏幕中的小部件之间传递数据。

示例代码:

这有点棘手。但是material.dart的小部件经常使用这种技术。我希望这能帮到您!

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  DateTime dateT;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Add a Reminder'),
      ),
      body: new Container(
        padding: new EdgeInsets.all(20.0),
        child: new Form(
          child: new ListView(
            children: <Widget>[
              new TextFormField(
                keyboardType: TextInputType.text,
                // Use email input type for emails.
                decoration: new InputDecoration(
                  hintText: 'Title of reminder',
                ),
              ),
              dateTime(
                onDateTimeChanged: (newDateTime) {
                  dateT = newDateTime;
                },
              ),
              RaisedButton(
                child: Text('Save'),
                onPressed: () {
                  Navigator.pop(context);
                },
              )
            ],
          ),
        ),
      ),
    );
  }
}

class dateTime extends StatefulWidget {
  final ValueChanged<DateTime> onDateTimeChanged;

  dateTime({Key key, this.onDateTimeChanged}) : super(key: key);

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

class dateTimeState extends State<dateTime> {
  DateTime dateT;

  InputType inputType = InputType.both;

  final formats = {
    InputType.both: DateFormat("EEEE, MMMM d, yyyy 'at' h:mma"),
    InputType.date: DateFormat('yyyy-MM-dd'),
    InputType.time: DateFormat("HH:mm"),
  };

  Widget build(BuildContext context) => Container(
        child: DateTimePickerFormField(
          inputType: InputType.both,
          editable: true,
          format: formats[inputType],
          decoration: InputDecoration(
              labelText: 'Date/Time', hasFloatingPlaceholder: false),
          onChanged: (dt) {
            widget.onDateTimeChanged(dt);
          },
        ),
      );
}
Run Code Online (Sandbox Code Playgroud)

(顺便说一句,你dateAndTimeWidget是一个方法,不是一个Widget。所以如果你把它赋值给Column的children(List),Flutter框架就无法理解。)


Uma*_*ooq 10

如需从另一个小部件返回值并使用它的更节省时间的解决方案,下面是 Flutter Dropdown 的示例:

import 'package:flutter/material.dart';
import 'package:paxi_ride/constant.dart';

class BuildDropdown extends StatefulWidget {
  final ValueChanged<String> onChanged;
  String defaultValue, selectedValue, dropdownHint;
  List<String> itemsList;

  BuildDropdown(
      {Key key,
      this.itemsList,
      this.defaultValue,
      this.dropdownHint,
      this.onChanged})
      : super(key: key);

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

class _BuildDropdownState extends State<BuildDropdown> {
  String _value;

  @override
  Widget build(BuildContext context) {
    return Container(
      // height: 40,
      padding: EdgeInsets.symmetric(horizontal: 16, vertical: 0),
      margin: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
      color: Colors.white,
      child: DropdownButton<String>(
        items: widget.itemsList.map(
          (String value) {
            return new DropdownMenuItem<String>(
              value: value,
              child: new Text(value),
            );
          },
        ).toList(),
        value: _value == null ? widget.defaultValue : _value,
        isExpanded: true,
        onChanged: (String value) {
          setState(() {
            _value = value;
          });
          widget.onChanged(value);
        },
        hint: Text(widget.dropdownHint),
        style: TextStyle(
          fontSize: 14,
          color: brownColorApp,
        ),
        iconEnabledColor: brownColorApp,
        iconSize: 14,
        underline: Container(),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

从另一个您想要获取选定值的小部件调用此小部件,如下所示:

String selectedValue; //class field

BuildDropdown(
          itemsList: ['Option 1','Option 2'],
          defaultValue: 'Option 1',
          dropdownHint: 'Select Required Option',
          onChanged: (value) {
            selectedValue = value;
          },
        ),
Run Code Online (Sandbox Code Playgroud)

在需要的地方使用此值,它将随着下拉选择的更改而更改。