showCupertinoModalPopup(
context: context,
builder: (context) => Container(
color: Colors.white,
height: 300,
child: CupertinoDatePicker(
mode: CupertinoDatePickerMode.date,
onDateTimeChanged: (dateTime) {
},
),
),
);
若需要将日期显示的英文改为中文,请参考官方文档:Flutter 国际化
如下图所示,需求为将日期选择顺序 月日年 改为 年月日。
3.1 查看 CupertinoDatePicker 源码
首先查看属性,并没有设置日期显示模式的属性,只有设置显示日期,日期+时间的显示模式 CupertinoDatePickerMode。
然后查看其build函数,发现年月日显示顺序与 localizations.datePickerDateOrder有关。
根据枚举类 DatePickerDateOrder 来判断年月日的显示顺序
3.2 查看 localizations.datePickerDateOrder
发现 datePickerDateOrder 与 CupertinoLocalizations 相关,flutter 中默认实现为 DefaultCupertinoLocalizations 仅适配了英文且默认情况下的日期选择模式为 mdy 月日年。
在 CupertinoDatePickerDateState 中可发现 localizations 来源于父级widget。
即来源于 CupertinoApp 或 MaterialApp 中的 localizationsDelegates
CupertinoApp(
localizationsDelegates: [
//默认值 不设置则会使用它
DefaultCupertinoLocalizations.delegate,
],
);
经过源码分析,立即想到的是自定义 CupertinoLocalizations。
如果完全自定义,在支持Flutter国际化之后,适配 GlobalCupertinoLocalizations时变得很麻烦。
下面采用一种简单的自定义方式来实现,只需修改 datePickerDateOrder的返回值,其它都使用父Widget的中的值。
class AppCupertinoLocalizations extends CupertinoLocalizations {
final CupertinoLocalizations _localizations;
AppCupertinoLocalizations(this._localizations);
//只改此处,其它的都原数据返回
@override
DatePickerDateOrder get datePickerDateOrder => DatePickerDateOrder.ymd;
@override
String datePickerYear(int yearIndex) => _localizations.datePickerYear(yearIndex);
@override
String get modalBarrierDismissLabel => _localizations.modalBarrierDismissLabel;
@override
String get selectAllButtonLabel => _localizations.selectAllButtonLabel;
@override
String get pasteButtonLabel => _localizations.pasteButtonLabel;
@override
String get copyButtonLabel => _localizations.copyButtonLabel;
@override
String get cutButtonLabel => _localizations.cutButtonLabel;
@override
String timerPickerSecondLabel(int second) => _localizations.timerPickerSecondLabel(second);
@override
String timerPickerMinuteLabel(int minute) => _localizations.timerPickerMinuteLabel(minute);
@override
String timerPickerHourLabel(int hour) => _localizations.timerPickerHourLabel(hour);
@override
String timerPickerSecond(int second) => _localizations.timerPickerSecond(second);
@override
String timerPickerMinute(int minute) => _localizations.timerPickerMinute(minute);
@override
String timerPickerHour(int hour) => _localizations.timerPickerHour(hour);
@override
String tabSemanticsLabel({
int tabIndex, int tabCount}) =>
_localizations.tabSemanticsLabel(tabIndex: tabIndex, tabCount: tabCount);
@override
String get alertDialogLabel => _localizations.alertDialogLabel;
@override
String get todayLabel => _localizations.todayLabel;
@override
String get postMeridiemAbbreviation => _localizations.postMeridiemAbbreviation;
@override
String get anteMeridiemAbbreviation => _localizations.anteMeridiemAbbreviation;
@override
DatePickerDateTimeOrder get datePickerDateTimeOrder => _localizations.datePickerDateTimeOrder;
@override
String datePickerMinuteSemanticsLabel(int minute) => _localizations.datePickerMinuteSemanticsLabel(minute);
@override
String datePickerMinute(int minute) => _localizations.datePickerMinute(minute);
@override
String datePickerHourSemanticsLabel(int hour) => _localizations.datePickerHourSemanticsLabel(hour);
@override
String datePickerHour(int hour) => _localizations.datePickerHour(hour);
@override
String datePickerMediumDate(DateTime date) => _localizations.datePickerMediumDate(date);
@override
String datePickerDayOfMonth(int dayIndex) => _localizations.datePickerDayOfMonth(dayIndex);
@override
String datePickerMonth(int monthIndex) => _localizations.datePickerMonth(monthIndex);
@override
String get searchTextFieldPlaceholderLabel => _localizations.searchTextFieldPlaceholderLabel;
@override
List<String> get timerPickerHourLabels => _localizations.timerPickerHourLabels;
@override
List<String> get timerPickerMinuteLabels => _localizations.timerPickerMinuteLabels;
@override
List<String> get timerPickerSecondLabels => _localizations.timerPickerSecondLabels;
}
代理类
class AppGlobalCupertinoLocalizationsDelegate extends LocalizationsDelegate<CupertinoLocalizations> {
@override
bool isSupported(Locale locale) => DefaultCupertinoLocalizations.delegate.isSupported(locale);
@override
Future<CupertinoLocalizations> load(Locale locale) async {
var localizations = await DefaultCupertinoLocalizations.delegate.load(locale);
return AppCupertinoLocalizations(localizations);
}
@override
bool shouldReload(LocalizationsDelegate<CupertinoLocalizations> old) =>
DefaultCupertinoLocalizations.delegate.shouldReload(old);
@override
String toString() => 'AppGlobalCupertinoLocalizationsDelegate';
}
使用Localizations.override
包裹CupertinoDatePicker,并修改 delegates
。
showCupertinoModalPopup(
context: context,
builder: (context) => Container(
color: Colors.white,
height: 300,
/// Overrides the inherited [Locale] or [LocalizationsDelegate]s for `child`.
child: Localizations.override(
context: context,
delegates: [AppGlobalCupertinoLocalizationsDelegate()],
child: CupertinoDatePicker(
mode: CupertinoDatePickerMode.date,
onDateTimeChanged: (dateTime) {
},
),
),
),
);
最终效果按 年月日 顺序显示日期