Flutter中如何通过DatePicker_Timeline获取选中日期?
解决date_picker_timeline获取选中日期的问题
我正在使用date_picker_timeline包(引入路径:import 'package:date_picker_timeline/date_picker_timeline.dart';),需要获取用户选中的日期。之前用TextEditingController可以直接通过controller.text获取输入内容,但DatePickerController不能这么用。尝试过DatePicker构造方法里的onDateChange属性,但没掌握正确的获取方式。已经实现了包含该时间选择器的AlertDialog,界面显示正常,但无法获取选中日期,相关代码如下:
// DialogBox代码 import 'package:flutter/material.dart'; import 'package:ghs/util/my_button.dart'; import 'package:date_picker_timeline/date_picker_timeline.dart'; class DialogBox extends StatelessWidget { final controllerKlinik; final controllerDate; DateTime selectedDate; VoidCallback onSave; VoidCallback onCancel; DialogBox({ super.key, required this.controllerKlinik, required this.controllerDate, required this.onSave, required this.onCancel, required this.selectedDate, }); @override Widget build(BuildContext context) { return AlertDialog( backgroundColor: Color.fromRGBO(252, 170, 0, 1.0), content: Container( height: 300, width: 300, child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ // get user input Date DatePicker( DateTime.now(), initialSelectedDate: DateTime.now().add(Duration(days: 3)), selectionColor: Colors.black, selectedTextColor: Colors.white, controller: controllerDate, ), //get user input Klinik TextField( controller: controllerKlinik, decoration: InputDecoration( border:OutlineInputBorder(), hintText: 'Datum' ), ), //buttons --> save + cancel Row( mainAxisAlignment: MainAxisAlignment.end, children: [ //save button MyButton(text: 'Save', onPressed: onSave), const SizedBox(width: 8,), //cancel button MyButton(text: 'Cancel', onPressed: onCancel), ], ) ], ) ), ); } }
// HomePage代码 import 'package:date_picker_timeline/date_picker_timeline.dart'; import 'package:flutter/material.dart'; import 'package:ghs/util/dialog_box.dart'; import 'package:ghs/util/time_tile.dart'; class HomePage extends StatefulWidget { const HomePage({super.key}); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { //text controller final _controllerKlinik = TextEditingController(); final _controllerDate = DatePickerController(); DateTime _selectedDate = DateTime.now(); //list of working hours List workingshift = [ [DateTime(2023,1,1), 8, 'Beispielklinik' ], [DateTime(2023,12,12), 6, 'Beispielklinik2' ], ]; // save new working shift void saveNewWorkingShift(){ setState(() { workingshift.add([_selectedDate, 7,_controllerKlinik.text]); _controllerKlinik.clear(); }); Navigator.of(context).pop(); } // create new working shift void createNewWorkingShift() { showDialog( context: context, builder: (context){ return DialogBox( controllerKlinik: _controllerKlinik, controllerDate: _controllerDate, selectedDate: _selectedDate, onSave: saveNewWorkingShift, onCancel: () => Navigator.of(context).pop(), ); }, ); } // delete working shift void deleteWorkingShift(int index){ setState(() { workingshift.removeAt(index); }); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.yellow[200], appBar: AppBar( title: Text('Zeiterfassung'), centerTitle: true, elevation: 0, ), floatingActionButton: FloatingActionButton( onPressed: createNewWorkingShift, child: Icon(Icons.add), ), body: ListView.builder( itemCount: workingshift.length, itemBuilder: (context,index){ return TimeTile( date: workingshift[index][0], workingHours: workingshift[index][1], klinik: workingshift[index][2], deleteFunction: (context) => deleteWorkingShift(index), ); }, ) ); } }
正确获取选中日期的两种实现方式
方式一:通过onDateChange回调实时同步选中日期
DatePicker的onDateChange会在用户选中新日期时触发,可通过该回调把选中日期同步到父组件的状态中:
- 给
DialogBox添加日期选择回调函数,用于传递选中的日期 - 在
DatePicker中绑定onDateChange,触发回调更新父组件的状态
修改后的DialogBox代码:
// DialogBox代码 import 'package:flutter/material.dart'; import 'package:ghs/util/my_button.dart'; import 'package:date_picker_timeline/date_picker_timeline.dart'; class DialogBox extends StatelessWidget { final TextEditingController controllerKlinik; final DatePickerController controllerDate; final DateTime selectedDate; final VoidCallback onSave; final VoidCallback onCancel; final Function(DateTime) onDateSelected; // 新增日期选择回调 DialogBox({ super.key, required this.controllerKlinik, required this.controllerDate, required this.selectedDate, required this.onSave, required this.onCancel, required this.onDateSelected, }); @override Widget build(BuildContext context) { return AlertDialog( backgroundColor: const Color.fromRGBO(252, 170, 0, 1.0), content: Container( height: 300, width: 300, child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ DatePicker( DateTime.now(), initialSelectedDate: selectedDate, selectionColor: Colors.black, selectedTextColor: Colors.white, controller: controllerDate, onDateChange: (date) { // 触发回调,将选中日期传递给父组件 onDateSelected(date); }, ), TextField( controller: controllerKlinik, decoration: const InputDecoration( border: OutlineInputBorder(), hintText: 'Klinik Name', ), ), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ MyButton(text: 'Save', onPressed: onSave), const SizedBox(width: 8), MyButton(text: 'Cancel', onPressed: onCancel), ], ) ], ), ), ); } }
修改HomePage中调用DialogBox的逻辑:
// create new working shift void createNewWorkingShift() { showDialog( context: context, builder: (context){ return DialogBox( controllerKlinik: _controllerKlinik, controllerDate: _controllerDate, selectedDate: _selectedDate, onSave: saveNewWorkingShift, onCancel: () => Navigator.of(context).pop(), onDateSelected: (date) { // 更新父组件的选中日期状态 setState(() { _selectedDate = date; }); }, ); }, ); }
方式二:直接通过DatePickerController获取选中日期
如果不需要实时同步,也可以在点击保存按钮时,直接从DatePickerController的selectedDate属性中读取当前选中日期:
修改HomePage的saveNewWorkingShift方法:
// save new working shift void saveNewWorkingShift(){ setState(() { // 从控制器获取选中日期,为空则使用默认值 final selectedDate = _controllerDate.selectedDate ?? _selectedDate; workingshift.add([selectedDate, 7,_controllerKlinik.text]); _controllerKlinik.clear(); }); Navigator.of(context).pop(); }
核心逻辑说明
DatePickerController和TextEditingController逻辑不同,它通过selectedDate属性存储当前选中的日期onDateChange是实时监听日期变化的回调,适合需要实时同步状态的场景- 由于
DialogBox是无状态组件,需要通过回调将选中日期传递给有状态的父组件HomePage维护状态
内容的提问来源于stack exchange,提问作者Musiker
相关产品推荐
相关产品推荐

