Flutter 修改iOS风格日期选择器CupertinoDatePicker的年月日排序方式

文章目录

  • 1. 需求描述
    • 1.1 如何显示iOS日期选择器
    • 1.2 需求
  • 2. 源码分析
  • 3 实现方式
    • 3.1 自定义CupertinoLocalizations
    • 3.2 使用自定义类


1. 需求描述

1.1 如何显示iOS日期选择器

    showCupertinoModalPopup(
      context: context,
      builder: (context) => Container(
        color: Colors.white,
        height: 300,
        child: CupertinoDatePicker(
          mode: CupertinoDatePickerMode.date,
          onDateTimeChanged: (dateTime) {
     },
        ),
      ),
    );

若需要将日期显示的英文改为中文,请参考官方文档:Flutter 国际化

1.2 需求

如下图所示,需求为将日期选择顺序 月日年 改为 年月日

Flutter 修改iOS风格日期选择器CupertinoDatePicker的年月日排序方式_第1张图片

2. 源码分析

3.1 查看 CupertinoDatePicker 源码

首先查看属性,并没有设置日期显示模式的属性,只有设置显示日期,日期+时间的显示模式 CupertinoDatePickerMode

然后查看其build函数,发现年月日显示顺序与 localizations.datePickerDateOrder有关。

Flutter 修改iOS风格日期选择器CupertinoDatePicker的年月日排序方式_第2张图片
根据枚举类 DatePickerDateOrder 来判断年月日的显示顺序

Flutter 修改iOS风格日期选择器CupertinoDatePicker的年月日排序方式_第3张图片
3.2 查看 localizations.datePickerDateOrder

发现 datePickerDateOrder 与 CupertinoLocalizations 相关,flutter 中默认实现为 DefaultCupertinoLocalizations 仅适配了英文且默认情况下的日期选择模式为 mdy 月日年。

在这里插入图片描述
3.3 查看 localizations 值来源

CupertinoDatePickerDateState 中可发现 localizations 来源于父级widget。

Flutter 修改iOS风格日期选择器CupertinoDatePicker的年月日排序方式_第4张图片
即来源于 CupertinoAppMaterialApp 中的 localizationsDelegates

    CupertinoApp(
      localizationsDelegates: [
        //默认值 不设置则会使用它
        DefaultCupertinoLocalizations.delegate,
      ],
    );

3 实现方式

经过源码分析,立即想到的是自定义 CupertinoLocalizations。

3.1 自定义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';
}

3.2 使用自定义类

使用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) {
     },
          ),
        ),
      ),
    );

最终效果按 年月日 顺序显示日期

Flutter 修改iOS风格日期选择器CupertinoDatePicker的年月日排序方式_第5张图片

你可能感兴趣的:(Flutter,flutter,ios,日期选择器,年月日,DatePicker)