如何在Flutter中实现范围日期选择器(无需使用Syncfusion包)
Flutter实现范围日期选择器(非Syncfusion方案)
以下是几种无需付费Syncfusion包的实现方案,覆盖基础需求到高度定制场景:
一、使用Flutter官方自带组件showDateRangePicker
这是最便捷的方案,无需额外依赖,完全免费且支持基础样式定制。
代码示例:
Future<void> _openRangePicker(BuildContext context) async { final DateTimeRange? pickedRange = await showDateRangePicker( context: context, firstDate: DateTime(2020), lastDate: DateTime(2030), // 设置初始选中范围 initialDateRange: DateTimeRange( start: DateTime.now(), end: DateTime.now().add(const Duration(days: 7)), ), // 自定义主题样式 builder: (context, child) { return Theme( data: ThemeData.light().copyWith( colorScheme: const ColorScheme.light( primary: Colors.blueAccent, // 选中日期的主色 onPrimary: Colors.white, surface: Colors.grey[100]!, ), dialogBackgroundColor: Colors.white, ), child: child!, ); }, ); if (pickedRange != null) { // 处理选中的日期范围 print('选中范围:${pickedRange.start} 至 ${pickedRange.end}'); } }
二、使用免费第三方包flutter_date_pickers
该包采用MIT许可,支持范围、单个、多个日期选择,样式定制更灵活。
步骤1:添加依赖
在pubspec.yaml中加入:
dependencies: flutter_date_pickers: ^2.0.0 # 请使用最新版本
代码示例:
import 'package:flutter_date_pickers/flutter_date_pickers.dart'; import 'package:flutter/material.dart'; class RangePickerPage extends StatefulWidget { const RangePickerPage({super.key}); @override State<RangePickerPage> createState() => _RangePickerPageState(); } class _RangePickerPageState extends State<RangePickerPage> { DateTimeRange _selectedRange = DateTimeRange( start: DateTime.now(), end: DateTime.now().add(const Duration(days: 3)), ); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('范围日期选择器')), body: Padding( padding: const EdgeInsets.all(16.0), child: RangePicker( selectedDateRange: _selectedRange, onChanged: (newRange) => setState(() => _selectedRange = newRange), firstDate: DateTime(2020), lastDate: DateTime(2030), datePickerStyles: DatePickerStyles( selectedDateStyle: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), selectedSingleDateDecoration: BoxDecoration( color: Colors.blueAccent, borderRadius: BorderRadius.circular(8), ), rangeMiddleDecoration: BoxDecoration( color: Colors.blueAccent.withOpacity(0.2), ), ), ), ), ); } }
三、基于TableCalendar自定义高度定制的选择器
如果需要完全控制UI细节(比如范围边框、渐变背景),可以使用MIT许可的TableCalendar包实现。
步骤1:添加依赖
dependencies: table_calendar: ^3.0.0 # 请使用最新版本
代码示例:
import 'package:table_calendar/table_calendar.dart'; import 'package:flutter/material.dart'; class CustomRangePicker extends StatefulWidget { const CustomRangePicker({super.key}); @override State<CustomRangePicker> createState() => _CustomRangePickerState(); } class _CustomRangePickerState extends State<CustomRangePicker> { DateTime? _focusedDay; DateTime? _rangeStart; DateTime? _rangeEnd; @override void initState() { super.initState(); _focusedDay = DateTime.now(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('自定义范围日期选择')), body: TableCalendar( firstDay: DateTime(2020), lastDay: DateTime(2030), focusedDay: _focusedDay!, rangeStartDay: _rangeStart, rangeEndDay: _rangeEnd, calendarFormat: CalendarFormat.month, onRangeSelected: (start, end, focusedDay) { setState(() { _rangeStart = start; _rangeEnd = end; _focusedDay = focusedDay; }); }, selectedDayPredicate: (day) => isSameDay(_rangeStart, day) || isSameDay(_rangeEnd, day), // 自定义范围样式 rangeStartDecoration: const BoxDecoration( color: Colors.blueAccent, borderRadius: BorderRadius.only( topLeft: Radius.circular(12), bottomLeft: Radius.circular(12), ), ), rangeEndDecoration: const BoxDecoration( color: Colors.blueAccent, borderRadius: BorderRadius.only( topRight: Radius.circular(12), bottomRight: Radius.circular(12), ), ), rangeMiddleDecoration: BoxDecoration( color: Colors.blueAccent.withOpacity(0.3), ), ), ); } }
内容的提问来源于stack exchange,提问作者Sabir Mondal
相关产品推荐
相关产品推荐

