You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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会在用户选中新日期时触发,可通过该回调把选中日期同步到父组件的状态中:

  1. 给DialogBox添加日期选择回调函数,用于传递选中的日期
  2. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 20:50:53