Do you really use the Flutter date component

The Flutter system provides some date selection components, such as DayPicker, MonthPicker, YearPicker, showDatePicker, Cupertino datepicker, etc. the first four are Material style components, and the last one is iOS style components. This paper introduces the basic usage of control and how to realize internationalization. If the internationalization provided by the system does not meet your needs, it also introduces how to realize custom internationalization.

DayPicker

Displays the date of a given month and allows one day to be selected. These days are arranged in a rectangular grid, with one column for each day of the week.

DayPicker has several required parameters, which are as follows:

  • Selected date: the selected date with a circular background.
  • currentDate: current date, highlighted text.
  • onChanged: callback when the date selected by the user changes.
  • firstDate: the start value of an optional date.
  • lastDate: the end value of an optional date.
  • displayedMonth: month displayed

Display may 2020, code as follows:

DateTime _selectedDate = DateTime.now();

DayPicker(
  selectedDate: _selectedDate,
  currentDate: DateTime.now(),
  onChanged: (date) {
    setState(() {
      _selectedDate = date;
    });
  },
  firstDate: DateTime(2020, 5, 1),
  lastDate: DateTime(2020, 5, 31),
  displayedMonth: DateTime(2020, 5),
)

The effect is as follows:

The selectableDayPredicate parameter defines the optional date of the user. If false is returned, it means that it is not optional. For example, only the date before today can be selected:

DayPicker(
  selectableDayPredicate: (date) {
    return date.difference(DateTime.now()).inMilliseconds < 0;
  },
  ...
)

The effect is as follows:

The dates after today are all gray, and cannot be selected.

MonthPicker

The optional month selector has a scrolling month list at the top. The days of the current month are displayed below each month. In essence, MonthPicker is a scrolling month list + DayPicker. The usage is as follows:

DateTime _selectedDate = DateTime.now();
MonthPicker(
  selectedDate: _selectedDate,
  onChanged: (date) {
    setState(() {
      _selectedDate = date;
    });
  },
  firstDate: DateTime(2020, 1),
  lastDate: DateTime(2020, 12),
)

The effect is as follows:

Properties are basically the same as DayPicker.

YearPicker

The year selector is used as follows:

YearPicker(
  selectedDate: _selectedDate,
  onChanged: (date) {
    setState(() {
      _selectedDate = date;
    });
  },
  firstDate: DateTime(2000, 1),
  lastDate: DateTime(2020, 12),
)

The effect is as follows:

The year selector is slightly different from the month selector in that it does not contain the month under the current year.

Whether it's YearPicker, MonthPicker or DayPicker, "we rarely use them directly", but use showDatePicker, which creates a date selector dialog box. I don't think the style of showDatePicker is very in line with the domestic aesthetic. We may use YearPicker, MonthPicker and DayPicker to customize the date control more often.

showDatePicker

showDatePicker is not a new control, but encapsulates YearPicker and MonthPicker, and links them. The usage is as follows:

RaisedButton(
  onPressed: () async {
    var result = await showDatePicker(
        context: context,
        initialDate: DateTime.now(),
        firstDate: DateTime(2020),
        lastDate: DateTime(2030));
    print('$result');
  },
)

The effect is as follows:

The relevant parameters are as follows:

  • initialDate initialization time, usually set to the current time.

  • The first date represents the start time, and the time before this time cannot be selected.

  • The lastDate represents the end time and cannot be selected after that time.

  • The showDatePicker method is the Future method. Click the OK button of the date selection control to return the selected date.

  • The selectableDayPredicate parameter defines the optional date of the user. If false is returned, it means it is not optional. It is the same as DayPicker.

The builder parameter can be used to wrap dialog widgets to add inherited widgets, such as Theme. The usage of setting a dark Theme is as follows:

showDatePicker(
  builder: (context, child) {
    return Theme(
      data: ThemeData.dark(),
      child: child,
    );
  },
	...
)

The effect is as follows:

The above is the Material style date control, and the following describes the iOS style date control.

CupertinoDatePicker

ios style date selector, which is used as follows:

 var _dateTime = DateTime.now();
CupertinoDatePicker(
  initialDateTime: _dateTime,
  onDateTimeChanged: (date) {
    setState(() {
      _dateTime = date;
    });
  },
)

The effect is as follows:

The mode parameter formats the date:

  • Time: display time only, effect: 4 | 14 | PM
  • Date: only show date, effect: July | 13 | 2012
  • dateAndTime: time and date are displayed, effect: Fri Jul 13 | 4 | 14 | PM

Set the maximum and minimum dates:

CupertinoDatePicker(
  minimumDate: DateTime.now().add(Duration(days: -1)),
  maximumDate: DateTime.now().add(Duration(days: 1)),
  ...
)

The effect is as follows:

Use the 24-hour system:

CupertinoDatePicker(
  use24hFormat: true,
	...
)

showTimePicker

The time selector can only be called by showTimePicker. The usage is as follows:

RaisedButton(
  onPressed: () async {
    showTimePicker(
        context: context, initialTime: TimeOfDay.now());
  },
)

The effect is as follows:

The builder parameter is used to control the child control. You can set the dark theme like the DatePicker, and also set its display for 24 hours. The usage is as follows:

showTimePicker(
    context: context,
    initialTime: TimeOfDay.now(),
    builder: (context, child) {
      return MediaQuery(
        data: MediaQuery.of(context)
            .copyWith(alwaysUse24HourFormat: true),
        child: child,
      );
    });

The effect is as follows:

CupertinoTimerPicker

Cupertino timerpicker is an ios style time selector. Its basic usage is as follows:

CupertinoTimerPicker(
  onTimerDurationChanged: (Duration duration){
  },
)

The effect is as follows:

Set to display only hours and minutes:

CupertinoTimerPicker(
  mode: CupertinoTimerPickerMode.hm,
  ...
)

By default, Cupertino timerpicker displays 0:0:0, setting the display current time:

var now = DateTime.now();
return Container(
  height: 200,
  child: CupertinoTimerPicker(
    initialTimerDuration: Duration(hours: now.hour,minutes: now.minute,seconds: now.second),
    onTimerDurationChanged: (Duration duration) {},
  ),
);

internationalization

Add internationalization processing and support in pubspec.yaml:

dependencies:
  flutter_localizations:
    sdk: flutter    

Add support in the top-level control MaterialApp. For details, see MaterialApp control:

MaterialApp(
  localeListResolutionCallback:
          (List<Locale> locales, Iterable<Locale> supportedLocales) {
        return Locale('zh');
      },
      localeResolutionCallback:
          (Locale locale, Iterable<Locale> supportedLocales) {
        return Locale('zh');
      },
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: [
        const Locale('zh', 'CH'),
        const Locale('en', 'US'),
      ],
  ...
)

The above method has effect on all date controls, and the effect is as follows:

Custom internationalization

For example, we define internationalization for iOS style controls, and create a new class MyLocalizationsDelegate:

class MyLocalizationsDelegate
    extends LocalizationsDelegate<CupertinoLocalizations> {
  const MyLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) => locale.languageCode == 'zh';

  @override
  Future<CupertinoLocalizations> load(Locale locale) =>
      ZhCupertinoLocalizations.load(locale);

  @override
  bool shouldReload(MyLocalizationsDelegate old) => false;

  @override
  String toString() => 'DefaultCupertinoLocalizations.delegate(zh)';
}

Zhcupertino localizations is defined as follows:

class ZhCupertinoLocalizations implements CupertinoLocalizations {
  const ZhCupertinoLocalizations();

  static const List<String> _shortWeekdays = <String>[
    'Since Monday',
    'Since Tuesday',
    'Since Wednesday',
    'Since Thursday',
    'Since Friday',
    'Since Saturday',
    'Since Sunday',
  ];

  static const List<String> _shortMonths = <String>[
    '1 month',
    '2 month',
    '3 month',
    '4 month',
    '5 month',
    '6 month',
    '7 month',
    '8 month',
    '9 month',
    '10 month',
    '11 month',
    '12 month',
  ];

  static const List<String> _months = <String>[
    '1 month',
    '2 month',
    '3 month',
    '4 month',
    '5 month',
    '6 month',
    '7 month',
    '8 month',
    '9 month',
    '10 month',
    '11 month',
    '12 month',
  ];

  @override
  String datePickerYear(int yearIndex) => yearIndex.toString();

  @override
  String datePickerMonth(int monthIndex) => _months[monthIndex - 1];

  @override
  String datePickerDayOfMonth(int dayIndex) => dayIndex.toString();

  @override
  String datePickerHour(int hour) => hour.toString();

  @override
  String datePickerHourSemanticsLabel(int hour) => hour.toString() + " o'clock";

  @override
  String datePickerMinute(int minute) => minute.toString().padLeft(2, '0');

  @override
  String datePickerMinuteSemanticsLabel(int minute) {
    if (minute == 1) return '1 branch';
    return minute.toString() + ' branch';
  }

  @override
  String datePickerMediumDate(DateTime date) {
    return '${_shortWeekdays[date.weekday - DateTime.monday]} '
        '${_shortMonths[date.month - DateTime.january]} '
        '${date.day.toString().padRight(2)}';
  }

  @override
  DatePickerDateOrder get datePickerDateOrder => DatePickerDateOrder.mdy;

  @override
  DatePickerDateTimeOrder get datePickerDateTimeOrder =>
      DatePickerDateTimeOrder.date_time_dayPeriod;

  @override
  String get anteMeridiemAbbreviation => 'morning';

  @override
  String get postMeridiemAbbreviation => 'Afternoon';

  @override
  String get todayLabel => 'Today';

  @override
  String get alertDialogLabel => 'Alert';

  @override
  String timerPickerHour(int hour) => hour.toString();

  @override
  String timerPickerMinute(int minute) => minute.toString();

  @override
  String timerPickerSecond(int second) => second.toString();

  @override
  String timerPickerHourLabel(int hour) => hour == 1 ? 'hour' : 'hour';

  @override
  String timerPickerMinuteLabel(int minute) => 'branch.';

  @override
  String timerPickerSecondLabel(int second) => 'second.';

  @override
  String get cutButtonLabel => 'Clip and paste';

  @override
  String get copyButtonLabel => 'Copy';

  @override
  String get pasteButtonLabel => 'Stick';

  @override
  String get selectAllButtonLabel => 'Select all';

  static Future<CupertinoLocalizations> load(Locale locale) {
    return SynchronousFuture<CupertinoLocalizations>(
        const ZhCupertinoLocalizations());
  }

  /// A [LocalizationsDelegate] that uses [DefaultCupertinoLocalizations.load]
  /// to create an instance of this class.
  static const LocalizationsDelegate<CupertinoLocalizations> delegate =
      MyLocalizationsDelegate();
}

Note that the initial attribute "shortWeekdays", which represents the day of the week, is intentionally written as "since week x". To distinguish it from the system, add "ZhCupertinoLocalizations.delegate" in the localizationsDelegates attribute of the root control MaterialApp. This is the international file defined above. The effect is as follows:

Note: ZhCupertinoLocalizations.delegate should be placed in front of GlobalCupertinoLocalizations.delegate, and the system loading order is from top to bottom.

The effect is as follows:

Communication

Address of laomeng Flutter blog (nearly 200 controls usage): http://laomengit.com

Welcome to Flutter exchange group (WeChat: laomengit) and official account [Lao Meng Flutter]:

Tags: Mobile iOS Attribute SDK

Posted on Fri, 08 May 2020 17:04:18 -0700 by dotbands