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

如何在Flutter中实现多日期选择功能?

Flutter 多选日期选择器实现方案

方案一:使用第三方包快速实现

不需要从零造轮子的场景下,优先用成熟的社区封装组件,核心实现成本极低:

  • 第一步在pubspec.yaml中添加依赖:
dependencies:
  flutter:
    sdk: flutter
  table_calendar: ^3.1.1 # 可替换为当前最新稳定版本
  • 核心页面代码示例:
import 'package:table_calendar/table_calendar.dart';
import 'package:flutter/material.dart';

class MultiSelectDatePicker extends StatefulWidget {
  const MultiSelectDatePicker({super.key});

  @override
  State<MultiSelectDatePicker> createState() => _MultiSelectDatePickerState();
}

class _MultiSelectDatePickerState extends State<MultiSelectDatePicker> {
  // 存储已选中的日期,用Set自动去重
  final Set<DateTime> _selectedDates = {};
  CalendarFormat _calendarFormat = CalendarFormat.month;
  DateTime _focusedDay = DateTime.now();

  // 统一清除日期的时分秒,避免判断异常
  DateTime _formatDate(DateTime date) => DateTime(date.year, date.month, date.day);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('多选日期')),
      body: TableCalendar(
        firstDay: DateTime.utc(2020, 1, 1),
        lastDay: DateTime.utc(2030, 12, 31),
        focusedDay: _focusedDay,
        calendarFormat: _calendarFormat,
        selectedDayPredicate: (day) => _selectedDates.contains(_formatDate(day)),
        onDaySelected: (selectedDay, focusedDay) {
          setState(() {
            _focusedDay = focusedDay;
            final formattedDay = _formatDate(selectedDay);
            _selectedDates.contains(formattedDay) 
                ? _selectedDates.remove(formattedDay) 
                : _selectedDates.add(formattedDay);
          });
        },
        onFormatChanged: (format) => setState(() => _calendarFormat = format),
        onPageChanged: (focusedDay) => _focusedDay = focusedDay,
        // 自定义日期样式
        calendarStyle: const CalendarStyle(
          selectedDecoration: BoxDecoration(color: Colors.blueAccent, shape: BoxShape.circle),
          todayDecoration: BoxDecoration(color: Colors.lightBlueAccent, shape: BoxShape.circle),
        ),
      ),
      // 确认选择后返回选中的日期列表
      floatingActionButton: FloatingActionButton.extended(
        onPressed: () => Navigator.pop(context, _selectedDates.toList()),
        label: const Text('确认选择'),
        icon: const Icon(Icons.check),
      ),
    );
  }
}

方案二:完全自定义实现

如果不想引入第三方依赖,可以自己封装组件,核心逻辑如下:

  • 计算当前月份的第一天、最后一天,以及需要在当前月视图里展示的上月、下月补位的日期
  • 用Set存储选中的日期,点击日期单元格时更新Set并触发UI重绘
  • 自定义单元格样式,区分选中态、今日、不可选日期的视觉表现
  • 按需添加上下月切换、周/月视图切换、范围选择限制等交互逻辑即可

注意所有日期对比、存储前都要统一清除时分秒部分,避免出现同一天因为时分秒不同被判定为不同日期的异常问题。

内容的提问来源于stack exchange,提问作者afsal.an

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 12:57:05