Cupertino日期选择器长滑年份轮越界抛出_AssertionError异常解决咨询
问题
在Android应用中,操作Cupertino日期选择器的年份轮进行“长滑”,使其越过设置的最小或最大年份时,会抛出如下断言异常:
Exception has occurred. _AssertionError ('package:flutter/src/cupertino/date_picker.dart': Failed assertion: line 327 pos 10: '(mode != CupertinoDatePickerMode.date && mode != CupertinoDatePickerMode.monthYear) || (minimumYear >= 1 && (initialDateTime ?? DateTime.now()).year >= minimumYear)': initial year is not greater than minimum year, or minimum year is not positive)
已正确设置initialDateTime为DateTime.now()、minimumYear=2000、maximumYear=2050,但异常仍会触发。
完整代码如下:
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { @override Widget build(BuildContext context) { return MaterialApp(home: const MyHomePage()); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { DateTime _dateTime = DateTime.now(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).primaryColor, title: const Text("Inbuild Cupertino Date Picker Example"), ), body: Column( children: [ Flexible( child: CupertinoDatePicker( initialDateTime: _dateTime, dateOrder: DatePickerDateOrder.ymd, mode: CupertinoDatePickerMode.date, minimumYear: 2000, maximumYear: 2050, onDateTimeChanged: (newDateTime) { print("############## DateTime: ${newDateTime}"); setState(() { _dateTime = newDateTime; }); }, ), ), ], ), bottomNavigationBar: Container( padding: EdgeInsets.all(15.0), height: 60.0, width: double.infinity, decoration: BoxDecoration(color: Colors.amberAccent), child: const Text("Bottom Navigation Bar"), ), ); } }
解决方法
问题根源是长滑操作时,Cupertino日期选择器会临时生成超出minimumYear/maximumYear范围的日期实例,触发内部的断言检查。解决思路是在更新状态前,先对新日期做范围校验,确保年份始终在设定的区间内:
- 在
onDateTimeChanged回调中,先判断新日期的年份是否超出范围 - 若超出,则修正为对应边界年份的有效日期(保持原月日,若原月日在边界年份无效则自动调整为当月最后一天)
- 再将修正后的日期更新到状态中
修改后的onDateTimeChanged代码如下:
onDateTimeChanged: (newDateTime) { print("############## DateTime: ${newDateTime}"); DateTime adjustedDateTime = newDateTime; // 校验并修正年份范围 if (adjustedDateTime.year < 2000) { adjustedDateTime = DateTime(2000, adjustedDateTime.month, adjustedDateTime.day); } else if (adjustedDateTime.year > 2050) { adjustedDateTime = DateTime(2050, adjustedDateTime.month, adjustedDateTime.day); } setState(() { _dateTime = adjustedDateTime; }); },
也可以封装成通用方法,方便复用:
DateTime _adjustDateTimeToRange(DateTime date, int minYear, int maxYear) { if (date.year < minYear) { return DateTime(minYear, date.month, date.day); } else if (date.year > maxYear) { return DateTime(maxYear, date.month, date.day); } return date; } // 在回调中使用 onDateTimeChanged: (newDateTime) { print("############## DateTime: ${newDateTime}"); setState(() { _dateTime = _adjustDateTimeToRange(newDateTime, 2000, 2050); }); },
这样处理后,长滑操作时生成的超出范围的日期会被提前修正,不会触发断言异常,同时保证用户选择的日期始终在设定的年份区间内。
内容的提问来源于stack exchange,提问作者rusty
相关产品推荐
相关产品推荐

