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

时间:2019-02-14 15:45:05

标签: flutter widget

我以前发布过有关此问题的信息,但我仍然面临 它将数据从有状态小部件返回到无状态小部件

我正在使用的小部件是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);
        },
      )
      ],
    ),)
    ,
    )
    ,
    );

  }

该小部件正在调用方法:dateAndTimeWidget,该方法应返回带状态的dateTime小部件并将结果数据保存在变量中:

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

}

然后这是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);
        },

      )


  );


}

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

2 个答案:

答案 0 :(得分:0)

在这种情况下,不适合使用Navigator传递数据。因为页面和您的dateTime小部件之间没有页面过渡。我建议您实现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);
          },
        ),
      );
}

(顺便说一下,您的dateAndTimeWidget是一种方法,不是小部件。因此,如果将其分配给Column的子级(列表),Flutter框架将无法理解。)

答案 1 :(得分:0)

要获得更多节省时间的解决方案,以从另一个小部件返回值并使用它,下面是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(),
      ),
    );
  }
}

从另一个您想要在其中获得选定值的小部件中调用此小部件:

String selectedValue; //class field

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

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