将控制器添加到自定义小部件

时间:2020-02-12 09:10:58

标签: flutter dart

我创建了一个自定义窗口小部件MyDateTimePicker,它基本上是一个TextFormField,可显示日期并允许用户在点击时选择日期。现在,我的问题是,我想从父窗口小部件中的另一个事件更新当前选择/显示的日期。起初,我想到为TextEditingController使用类似TextFormField的控制器。不幸的是,我不确定该怎么做,所以我走了最后一条路,那就是对小部件状态使用全局键,并使用该键从父小部件中调用更新功能。就像很多人会说的那样,请避免使用全局键,因此我想改用控制器。我希望您能在可能的情况下帮助我如何为自定义小部件使用控制器。谢谢!

class MyDateTimePicker extends StatefulWidget {
  const MyDateTimePicker(
      {Key key,
      this.labelText,
      @required this.initialDate,
      this.onValueChanged})
      : super(key: key);

  final String labelText;
  final DateTime initialDate;
  final ValueChanged<DateTime> onValueChanged;

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

class MyDateTimePickerState extends State<MyDateTimePicker> {
  final TextEditingController _controller = TextEditingController();
  DateTime _selectedDate;

  @override
  void initState() {
    super.initState();
    _selectedDate = widget.initialDate;
    _controller.text = DateFormat.yMMMd().format(_selectedDate);
  }

  // Called by the parent widget through a global key.
  void setDate(DateTime date) {
    _selectedDate = date;
    _controller.text = DateFormat.yMMMd().format(_selectedDate);
  }

  Future<void> _selectDate(BuildContext context) async {
    final DateTime picked = await showDatePicker(
        context: context,
        initialDate: _selectedDate,
        firstDate: DateTime(1970, 8),
        lastDate: DateTime(2101));
    if (picked != null && picked != _selectedDate) {
      _selectedDate = picked;
      _controller.text = DateFormat.yMMMd().format(_selectedDate);
      widget.onValueChanged(picked);
    }
  }

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      controller: _controller,
      decoration: InputDecoration(
        border: const OutlineInputBorder(
          borderRadius: BorderRadius.all(Radius.circular(5.0)),
        ),
        contentPadding: const EdgeInsets.symmetric(vertical: 0.0),
        labelText: widget.labelText,
        prefixIcon: Icon(Icons.calendar_today),
        suffixIcon: Icon(Icons.arrow_drop_down),
      ),
      readOnly: true,
      onTap: () {
        _selectDate(context);
      },
    );
  }
}

1 个答案:

答案 0 :(得分:0)

您可以像这样将TextEditingController作为MyDateTimePicker小部件的参数传递:

class MyDateTimePicker extends StatefulWidget {
  const MyDateTimePicker({
    Key key,
    this.labelText,
    @required this.initialDate,
    this.onValueChanged,
    @required this.controller,
  }) : super(key: key);

  final String labelText;
  final DateTime initialDate;
  final ValueChanged<DateTime> onValueChanged;
  final TextEditingController controller;

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

class MyDateTimePickerState extends State<MyDateTimePicker> {
  DateTime _selectedDate;

  @override
  void initState() {
    super.initState();
    _selectedDate = widget.initialDate;
    widget.controller.text = DateFormat.yMMMd().format(_selectedDate);
  }

  // Called by the parent widget through a global key.
  void setDate(DateTime date) {
    _selectedDate = date;
    widget.controller.text = DateFormat.yMMMd().format(_selectedDate);
  }

  Future<void> _selectDate(BuildContext context) async {
    final DateTime picked = await showDatePicker(
        context: context,
        initialDate: _selectedDate,
        firstDate: DateTime(1970, 8),
        lastDate: DateTime(2101));
    if (picked != null && picked != _selectedDate) {
      _selectedDate = picked;
      widget.controller.text = DateFormat.yMMMd().format(_selectedDate);
      widget.onValueChanged(picked);
    }
  }

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      controller: widget.controller,
      decoration: InputDecoration(
        border: const OutlineInputBorder(
          borderRadius: BorderRadius.all(Radius.circular(5.0)),
        ),
        contentPadding: const EdgeInsets.symmetric(vertical: 0.0),
        labelText: widget.labelText,
        prefixIcon: Icon(Icons.calendar_today),
        suffixIcon: Icon(Icons.arrow_drop_down),
      ),
      readOnly: true,
      onTap: () {
        _selectDate(context);
      },
    );
  }
}
相关问题