Flutter如何实现日历和时间段组件

在Flutter中想要实现一个自定义的日历和时间段选择组件,应该使用什么插件或方法比较合适?目前看到有table_calendar和syncfusion_flutter_calendar等插件,但不太清楚它们的具体区别和适用场景。另外,如果需要支持跨月份的时间段选择(比如选择7天跨越两个月份),以及自定义UI样式(如高亮特定日期),这些插件能否满足需求?希望有经验的大佬能分享一下实现方案和注意事项。

2 回复

Flutter中可使用table_calendar库实现日历组件,支持日期选择和范围选择。时间段组件可用flutter_datetime_picker或自定义ListView展示时间槽。两者结合可满足常见需求。

更多关于Flutter如何实现日历和时间段组件的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中实现日历和时间段组件,可以使用以下方案:

1. 日历组件

使用 table_calendar 库(推荐)

dependencies:
  table_calendar: ^3.0.9
import 'package:table_calendar/table_calendar.dart';

class CalendarWidget extends StatefulWidget {
  @override
  _CalendarWidgetState createState() => _CalendarWidgetState();
}

class _CalendarWidgetState extends State<CalendarWidget> {
  CalendarFormat _calendarFormat = CalendarFormat.month;
  DateTime _focusedDay = DateTime.now();
  DateTime? _selectedDay;

  @override
  Widget build(BuildContext context) {
    return TableCalendar(
      firstDay: DateTime.utc(2020, 1, 1),
      lastDay: DateTime.utc(2030, 12, 31),
      focusedDay: _focusedDay,
      calendarFormat: _calendarFormat,
      selectedDayPredicate: (day) {
        return isSameDay(_selectedDay, day);
      },
      onDaySelected: (selectedDay, focusedDay) {
        setState(() {
          _selectedDay = selectedDay;
          _focusedDay = focusedDay;
        });
      },
      onFormatChanged: (format) {
        setState(() {
          _calendarFormat = format;
        });
      },
      onPageChanged: (focusedDay) {
        _focusedDay = focusedDay;
      },
    );
  }
}

2. 时间段选择组件

自定义时间段选择器

import 'package:flutter/material.dart';

class TimeRangePicker extends StatefulWidget {
  @override
  _TimeRangePickerState createState() => _TimeRangePickerState();
}

class _TimeRangePickerState extends State<TimeRangePicker> {
  TimeOfDay? _startTime;
  TimeOfDay? _endTime;

  Future<void> _selectStartTime() async {
    final TimeOfDay? picked = await showTimePicker(
      context: context,
      initialTime: _startTime ?? TimeOfDay.now(),
    );
    if (picked != null) {
      setState(() {
        _startTime = picked;
      });
    }
  }

  Future<void> _selectEndTime() async {
    final TimeOfDay? picked = await showTimePicker(
      context: context,
      initialTime: _endTime ?? TimeOfDay.now(),
    );
    if (picked != null) {
      setState(() {
        _endTime = picked;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ListTile(
          title: Text('开始时间: ${_startTime?.format(context) ?? "未选择"}'),
          trailing: Icon(Icons.access_time),
          onTap: _selectStartTime,
        ),
        ListTile(
          title: Text('结束时间: ${_endTime?.format(context) ?? "未选择"}'),
          trailing: Icon(Icons.access_time),
          onTap: _selectEndTime,
        ),
      ],
    );
  }
}

3. 集成日历和时间段

class DateTimeRangePicker extends StatefulWidget {
  @override
  _DateTimeRangePickerState createState() => _DateTimeRangePickerState();
}

class _DateTimeRangePickerState extends State<DateTimeRangePicker> {
  DateTime? _selectedDate;
  TimeOfDay? _startTime;
  TimeOfDay? _endTime;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // 日历组件
        TableCalendar(
          focusedDay: DateTime.now(),
          firstDay: DateTime.now(),
          lastDay: DateTime.now().add(Duration(days: 365)),
          selectedDayPredicate: (day) => isSameDay(_selectedDate, day),
          onDaySelected: (selectedDay, focusedDay) {
            setState(() {
              _selectedDate = selectedDay;
            });
          },
        ),
        SizedBox(height: 20),
        // 时间段选择
        TimeRangePicker(),
      ],
    );
  }
}

其他推荐库

  • flutter_calendar_carousel: 轮播式日历
  • date_range_picker: 日期范围选择
  • syncfusion_flutter_calendar: 功能丰富的日历组件

这些方案可以满足大部分日历和时间段选择的需求,table_calendar 是最常用的日历库,功能完善且易于使用。

回到顶部