Unverified Commit 142b526f authored by Darren Austin's avatar Darren Austin Committed by GitHub

Material Date Picker redesign (#50546)

Date Picker UI redesign
parent 25ef78e2
......@@ -41,17 +41,23 @@ ConstructorGenerator generateMaterialConstructor = (LocaleInfo locale) {
const MaterialLocalization${locale.camelCase()}({
String localeName = '$localeName',
@required intl.DateFormat fullYearFormat,
@required intl.DateFormat compactDateFormat,
@required intl.DateFormat shortDateFormat,
@required intl.DateFormat mediumDateFormat,
@required intl.DateFormat longDateFormat,
@required intl.DateFormat yearMonthFormat,
@required intl.DateFormat shortMonthDayFormat,
@required intl.NumberFormat decimalFormat,
@required intl.NumberFormat twoDigitZeroPaddedFormat,
}) : super(
localeName: localeName,
fullYearFormat: fullYearFormat,
compactDateFormat: compactDateFormat,
shortDateFormat: shortDateFormat,
mediumDateFormat: mediumDateFormat,
longDateFormat: longDateFormat,
yearMonthFormat: yearMonthFormat,
shortMonthDayFormat: shortMonthDayFormat,
decimalFormat: decimalFormat,
twoDigitZeroPaddedFormat: twoDigitZeroPaddedFormat,
);''';
......@@ -63,15 +69,18 @@ const String materialFactoryDeclaration = '''
GlobalMaterialLocalizations getMaterialTranslation(
Locale locale,
intl.DateFormat fullYearFormat,
intl.DateFormat compactDateFormat,
intl.DateFormat shortDateFormat,
intl.DateFormat mediumDateFormat,
intl.DateFormat longDateFormat,
intl.DateFormat yearMonthFormat,
intl.DateFormat shortMonthDayFormat,
intl.NumberFormat decimalFormat,
intl.NumberFormat twoDigitZeroPaddedFormat,
) {''';
const String materialFactoryArguments =
'fullYearFormat: fullYearFormat, mediumDateFormat: mediumDateFormat, longDateFormat: longDateFormat, yearMonthFormat: yearMonthFormat, decimalFormat: decimalFormat, twoDigitZeroPaddedFormat: twoDigitZeroPaddedFormat';
'fullYearFormat: fullYearFormat, compactDateFormat: compactDateFormat, shortDateFormat: shortDateFormat, mediumDateFormat: mediumDateFormat, longDateFormat: longDateFormat, yearMonthFormat: yearMonthFormat, shortMonthDayFormat: shortMonthDayFormat, decimalFormat: decimalFormat, twoDigitZeroPaddedFormat: twoDigitZeroPaddedFormat';
const String materialSupportedLanguagesConstant = 'kMaterialSupportedLanguages';
......
......@@ -46,7 +46,6 @@ export 'src/material/colors.dart';
export 'src/material/constants.dart';
export 'src/material/data_table.dart';
export 'src/material/data_table_source.dart';
export 'src/material/date_picker.dart';
export 'src/material/debug.dart';
export 'src/material/dialog.dart';
export 'src/material/dialog_theme.dart';
......@@ -86,6 +85,7 @@ export 'src/material/outline_button.dart';
export 'src/material/page.dart';
export 'src/material/page_transitions_theme.dart';
export 'src/material/paginated_data_table.dart';
export 'src/material/pickers/pickers.dart';
export 'src/material/popup_menu.dart';
export 'src/material/popup_menu_theme.dart';
export 'src/material/progress_indicator.dart';
......
......@@ -224,6 +224,29 @@ abstract class MaterialLocalizations {
/// Full unabbreviated year format, e.g. 2017 rather than 17.
String formatYear(DateTime date);
/// Formats the date in a compact format.
///
/// Usually just the numeric values for the for day, month and year are used.
///
/// Examples:
///
/// - US English: 02/21/2019
/// - Russian: 21.02.2019
///
/// See also:
/// * [parseCompactDate], which will convert a compact date string to a [DateTime].
String formatCompactDate(DateTime date);
/// Formats the date using a short-width format.
///
/// Includes the abbreviation of the month, the day and year.
///
/// Examples:
///
/// - US English: Feb 21, 2019
/// - Russian: 21 февр. 2019 г.
String formatShortDate(DateTime date);
/// Formats the date using a medium-width format.
///
/// Abbreviates month and days of week. This appears in the header of the date
......@@ -252,6 +275,24 @@ abstract class MaterialLocalizations {
/// in the date picker invoked using [showDatePicker].
String formatMonthYear(DateTime date);
/// Formats the month and day of the given [date].
///
/// Examples:
///
/// - US English: Feb 21
/// - Russian: 21 февр.
String formatShortMonthDay(DateTime date);
/// Converts the given compact date formatted string into a [DateTime].
///
/// The format of the string must be a valid compact date format for the
/// given locale. If the text doesn't represent a valid date, `null` will be
/// returned.
///
/// See also:
/// * [formatCompactDate], which will convert a [DateTime] into a string in the compact format.
DateTime parseCompactDate(String inputString);
/// List of week day names in narrow format, usually 1- or 2-letter
/// abbreviations of full names.
///
......@@ -437,6 +478,23 @@ class DefaultMaterialLocalizations implements MaterialLocalizations {
'December',
];
/// Returns the number of days in a month, according to the proleptic
/// Gregorian calendar.
///
/// This applies the leap year logic introduced by the Gregorian reforms of
/// 1582. It will not give valid results for dates prior to that time.
int _getDaysInMonth(int year, int month) {
if (month == DateTime.february) {
final bool isLeapYear = (year % 4 == 0) && (year % 100 != 0) ||
(year % 400 == 0);
if (isLeapYear)
return 29;
return 28;
}
const List<int> daysInMonth = <int>[31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
return daysInMonth[month - 1];
}
@override
String formatHour(TimeOfDay timeOfDay, { bool alwaysUse24HourFormat = false }) {
final TimeOfDayFormat format = timeOfDayFormat(alwaysUse24HourFormat: alwaysUse24HourFormat);
......@@ -470,6 +528,21 @@ class DefaultMaterialLocalizations implements MaterialLocalizations {
@override
String formatYear(DateTime date) => date.year.toString();
@override
String formatCompactDate(DateTime date) {
// Assumes US mm/dd/yyyy format
final String month = _formatTwoDigitZeroPad(date.month);
final String day = _formatTwoDigitZeroPad(date.day);
final String year = date.year.toString().padLeft(4, '0');
return '$month/$day/$year';
}
@override
String formatShortDate(DateTime date) {
final String month = _shortMonths[date.month - DateTime.january];
return '$month ${date.day}, ${date.year}';
}
@override
String formatMediumDate(DateTime date) {
final String day = _shortWeekdays[date.weekday - DateTime.monday];
......@@ -490,6 +563,37 @@ class DefaultMaterialLocalizations implements MaterialLocalizations {
return '$month $year';
}
@override
String formatShortMonthDay(DateTime date) {
final String month = _shortMonths[date.month - DateTime.january];
return '$month ${date.day}';
}
@override
DateTime parseCompactDate(String inputString) {
// Assumes US mm/dd/yyyy format
final List<String> inputParts = inputString.split('/');
if (inputParts.length != 3) {
return null;
}
final int year = int.tryParse(inputParts[2], radix: 10);
if (year == null || year < 1) {
return null;
}
final int month = int.tryParse(inputParts[0], radix: 10);
if (month == null || month < 1 || month > 12) {
return null;
}
final int day = int.tryParse(inputParts[1], radix: 10);
if (day == null || day < 1 || day > _getDaysInMonth(year, month)) {
return null;
}
return DateTime(year, month, day);
}
@override
List<String> get narrowWeekdays => _narrowWeekdays;
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/// Mode of the date picker dialog.
///
/// Either a calendar or text input. In [calendar] mode, a calendar view is
/// displayed and the user taps the day they wish to select. In [input] mode a
/// [TextField] is displayed and the user types in the date they wish to select.
enum DatePickerEntryMode {
/// Tapping on a calendar.
calendar,
/// Text input.
input,
}
/// Initial display of a calendar date picker.
///
/// Either a grid of available years or a monthly calendar.
///
/// See also:
///
/// * [showDatePicker], which shows a dialog that contains a material design
/// date picker.
/// * [CalendarDatePicker], widget which implements the material design date picker.
enum DatePickerMode {
/// Choosing a month and day.
day,
/// Choosing a year.
year,
}
/// Signature for predicating dates for enabled date selections.
///
/// See [showDatePicker].
typedef SelectableDayPredicate = bool Function(DateTime day);
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/widgets.dart';
import '../color_scheme.dart';
import '../icon_button.dart';
import '../text_theme.dart';
import '../theme.dart';
// NOTE: This is an internal implementation file. Even though there are public
// classes and functions defined here, they are only meant to be used by the
// date picker implementation and are not exported as part of the Material library.
// See pickers.dart for exactly what is considered part of the public API.
const double _datePickerHeaderLandscapeWidth = 152.0;
const double _datePickerHeaderPortraitHeight = 120.0;
const double _headerPaddingLandscape = 16.0;
/// Re-usable widget that displays the selected date (in large font) and the
/// help text above it.
///
/// These types include:
///
/// * Single Date picker with calendar mode.
/// * Single Date picker with manual input mode.
///
/// [helpText], [orientation], [icon], [onIconPressed] are required and must be
/// non-null.
class DatePickerHeader extends StatelessWidget {
/// Creates a header for use in a date picker dialog.
const DatePickerHeader({
Key key,
@required this.helpText,
@required this.titleText,
this.titleSemanticsLabel,
@required this.titleStyle,
@required this.orientation,
this.isShort = false,
@required this.icon,
@required this.iconTooltip,
@required this.onIconPressed,
}) : assert(helpText != null),
assert(orientation != null),
assert(isShort != null),
super(key: key);
/// The text that is displayed at the top of the header.
///
/// This is used to indicate to the user what they are selecting a date for.
final String helpText;
/// The text that is displayed at the center of the header.
final String titleText;
/// The semantic label associated with the [titleText].
final String titleSemanticsLabel;
/// The [TextStyle] that the title text is displayed with.
final TextStyle titleStyle;
/// The orientation is used to decide how to layout its children.
final Orientation orientation;
/// Indicates the header is being displayed in a shorter/narrower context.
///
/// This will be used to tighten up the space between the help text and date
/// text if `true`. Additionally, it will use a smaller typography style if
/// `true`.
///
/// This is necessary for displaying the manual input mode in
/// landscape orientation, in order to account for the keyboard height.
final bool isShort;
/// The mode-switching icon that will be displayed in the lower right
/// in portrait, and lower left in landscape.
///
/// The available icons are described in [Icons].
final IconData icon;
/// The text that is displayed for the tooltip of the icon.
final String iconTooltip;
/// Callback when the user taps the icon in the header.
///
/// The picker will use this to toggle between entry modes.
final VoidCallback onIconPressed;
@override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
final ColorScheme colorScheme = theme.colorScheme;
final TextTheme textTheme = theme.textTheme;
// The header should use the primary color in light themes and surface color in dark
final bool isDark = colorScheme.brightness == Brightness.dark;
final Color primarySurfaceColor = isDark ? colorScheme.surface : colorScheme.primary;
final Color onPrimarySurfaceColor = isDark ? colorScheme.onSurface : colorScheme.onPrimary;
final TextStyle helpStyle = textTheme.overline?.copyWith(
color: onPrimarySurfaceColor,
);
final Text help = Text(
helpText,
style: helpStyle,
maxLines: 1,
overflow: TextOverflow.ellipsis,
);
final Text title = Text(
titleText,
semanticsLabel: titleSemanticsLabel ?? titleText,
style: titleStyle,
maxLines: (isShort || orientation == Orientation.portrait) ? 1 : 2,
overflow: TextOverflow.ellipsis,
);
final IconButton icon = IconButton(
icon: Icon(this.icon),
color: onPrimarySurfaceColor,
tooltip: iconTooltip,
onPressed: onIconPressed,
);
switch (orientation) {
case Orientation.portrait:
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
height: _datePickerHeaderPortraitHeight,
color: primarySurfaceColor,
padding: const EdgeInsetsDirectional.only(
start: 24,
end: 12,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const SizedBox(height: 16),
Flexible(child: help),
const SizedBox(height: 38),
Row(
children: <Widget>[
Expanded(child: title),
icon,
],
),
],
),
),
],
);
case Orientation.landscape:
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: _datePickerHeaderLandscapeWidth,
color: primarySurfaceColor,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const SizedBox(height: 16),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: _headerPaddingLandscape,
),
child: help,
),
SizedBox(height: isShort ? 16 : 56),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: _headerPaddingLandscape,
),
child: title,
),
const Spacer(),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 4,
),
child: icon,
),
],
),
),
],
);
}
return null;
}
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Common date utility functions used by the date picker implementation
// NOTE: This is an internal implementation file. Even though there are public
// classes and functions defined here, they are only meant to be used by the
// date picker implementation and are not exported as part of the Material library.
// See pickers.dart for exactly what is considered part of the public API.
import '../material_localizations.dart';
/// Returns a [DateTime] with just the date of the original, but no time set.
DateTime dateOnly(DateTime date) {
return DateTime(date.year, date.month, date.day);
}
/// Returns true if the two [DateTime] objects have the same day, month, and
/// year.
bool isSameDay(DateTime dateA, DateTime dateB) {
return
dateA.year == dateB.year &&
dateA.month == dateB.month &&
dateA.day == dateB.day;
}
/// Determines the number of months between two [DateTime] objects.
///
/// For example:
/// ```
/// DateTime date1 = DateTime(year: 2019, month: 6, day: 15);
/// DateTime date2 = DateTime(year: 2020, month: 1, day: 15);
/// int delta = monthDelta(date1, date2);
/// ```
///
/// The value for `delta` would be `7`.
int monthDelta(DateTime startDate, DateTime endDate) {
return (endDate.year - startDate.year) * 12 + endDate.month - startDate.month;
}
/// Returns a [DateTime] with the added number of months and truncates any day
/// and time information.
///
/// For example:
/// ```
/// DateTime date = DateTime(year: 2019, month: 1, day: 15);
/// DateTime futureDate = _addMonthsToMonthDate(date, 3);
/// ```
///
/// `date` would be January 15, 2019.
/// `futureDate` would be April 1, 2019 since it adds 3 months and truncates
/// any additional date information.
DateTime addMonthsToMonthDate(DateTime monthDate, int monthsToAdd) {
return DateTime(monthDate.year, monthDate.month + monthsToAdd);
}
/// Computes the offset from the first day of the week that the first day of
/// the [month] falls on.
///
/// For example, September 1, 2017 falls on a Friday, which in the calendar
/// localized for United States English appears as:
///
/// ```
/// S M T W T F S
/// _ _ _ _ _ 1 2
/// ```
///
/// The offset for the first day of the months is the number of leading blanks
/// in the calendar, i.e. 5.
///
/// The same date localized for the Russian calendar has a different offset,
/// because the first day of week is Monday rather than Sunday:
///
/// ```
/// M T W T F S S
/// _ _ _ _ 1 2 3
/// ```
///
/// So the offset is 4, rather than 5.
///
/// This code consolidates the following:
///
/// - [DateTime.weekday] provides a 1-based index into days of week, with 1
/// falling on Monday.
/// - [MaterialLocalizations.firstDayOfWeekIndex] provides a 0-based index
/// into the [MaterialLocalizations.narrowWeekdays] list.
/// - [MaterialLocalizations.narrowWeekdays] list provides localized names of
/// days of week, always starting with Sunday and ending with Saturday.
int firstDayOffset(int year, int month, MaterialLocalizations localizations) {
// 0-based day of week for the month and year, with 0 representing Monday.
final int weekdayFromMonday = DateTime(year, month).weekday - 1;
// 0-based start of week depending on the locale, with 0 representing Sunday.
int firstDayOfWeekIndex = localizations.firstDayOfWeekIndex;
// firstDayOfWeekIndex recomputed to be Monday-based, in order to compare with
// weekdayFromMonday.
firstDayOfWeekIndex = (firstDayOfWeekIndex - 1) % 7;
// Number of days between the first day of week appearing on the calendar,
// and the day corresponding to the first of the month.
return (weekdayFromMonday - firstDayOfWeekIndex) % 7;
}
/// Returns the number of days in a month, according to the proleptic
/// Gregorian calendar.
///
/// This applies the leap year logic introduced by the Gregorian reforms of
/// 1582. It will not give valid results for dates prior to that time.
int getDaysInMonth(int year, int month) {
if (month == DateTime.february) {
final bool isLeapYear = (year % 4 == 0) && (year % 100 != 0) ||
(year % 400 == 0);
if (isLeapYear)
return 29;
return 28;
}
const List<int> daysInMonth = <int>[31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
return daysInMonth[month - 1];
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Date Picker public API
export 'calendar_date_picker.dart' show CalendarDatePicker;
export 'date_picker_common.dart' show DatePickerEntryMode, DatePickerMode, SelectableDayPredicate;
export 'date_picker_deprecated.dart';
export 'date_picker_dialog.dart' show showDatePicker;
export 'input_date_picker.dart' show InputDatePickerFormField;
......@@ -76,12 +76,14 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// 1. The string that would be returned by [Intl.canonicalizedLocale] for
/// the locale.
/// 2. The [intl.DateFormat] for [formatYear].
/// 3. The [intl.DateFormat] for [formatMediumDate].
/// 4. The [intl.DateFormat] for [formatFullDate].
/// 5. The [intl.DateFormat] for [formatMonthYear].
/// 6. The [NumberFormat] for [formatDecimal] (also used by [formatHour] and
/// 3. The [int.DateFormat] for [formatShortDate].
/// 4. The [intl.DateFormat] for [formatMediumDate].
/// 5. The [intl.DateFormat] for [formatFullDate].
/// 6. The [intl.DateFormat] for [formatMonthYear].
/// 7. The [int.DateFormat] for [formatShortMonthDay].
/// 8. The [NumberFormat] for [formatDecimal] (also used by [formatHour] and
/// [formatTimeOfDay] when [timeOfDayFormat] doesn't use [HourFormat.HH]).
/// 7. The [NumberFormat] for [formatHour] and the hour part of
/// 9. The [NumberFormat] for [formatHour] and the hour part of
/// [formatTimeOfDay] when [timeOfDayFormat] uses [HourFormat.HH], and for
/// [formatMinute] and the minute part of [formatTimeOfDay].
///
......@@ -90,21 +92,30 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
const GlobalMaterialLocalizations({
@required String localeName,
@required intl.DateFormat fullYearFormat,
@required intl.DateFormat compactDateFormat,
@required intl.DateFormat shortDateFormat,
@required intl.DateFormat mediumDateFormat,
@required intl.DateFormat longDateFormat,
@required intl.DateFormat yearMonthFormat,
@required intl.DateFormat shortMonthDayFormat,
@required intl.NumberFormat decimalFormat,
@required intl.NumberFormat twoDigitZeroPaddedFormat,
}) : assert(localeName != null),
_localeName = localeName,
assert(fullYearFormat != null),
_fullYearFormat = fullYearFormat,
assert(compactDateFormat != null),
_compactDateFormat = compactDateFormat,
assert(shortDateFormat != null),
_shortDateFormat = shortDateFormat,
assert(mediumDateFormat != null),
_mediumDateFormat = mediumDateFormat,
assert(longDateFormat != null),
_longDateFormat = longDateFormat,
assert(yearMonthFormat != null),
_yearMonthFormat = yearMonthFormat,
assert(shortMonthDayFormat != null),
_shortMonthDayFormat = shortMonthDayFormat,
assert(decimalFormat != null),
_decimalFormat = decimalFormat,
assert(twoDigitZeroPaddedFormat != null),
......@@ -112,9 +123,12 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
final String _localeName;
final intl.DateFormat _fullYearFormat;
final intl.DateFormat _compactDateFormat;
final intl.DateFormat _shortDateFormat;
final intl.DateFormat _mediumDateFormat;
final intl.DateFormat _longDateFormat;
final intl.DateFormat _yearMonthFormat;
final intl.DateFormat _shortMonthDayFormat;
final intl.NumberFormat _decimalFormat;
final intl.NumberFormat _twoDigitZeroPaddedFormat;
......@@ -142,6 +156,16 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
return _fullYearFormat.format(date);
}
@override
String formatCompactDate(DateTime date) {
return _compactDateFormat.format(date);
}
@override
String formatShortDate(DateTime date) {
return _shortDateFormat.format(date);
}
@override
String formatMediumDate(DateTime date) {
return _mediumDateFormat.format(date);
......@@ -157,6 +181,20 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
return _yearMonthFormat.format(date);
}
@override
String formatShortMonthDay(DateTime date) {
return _shortMonthDayFormat.format(date);
}
@override
DateTime parseCompactDate(String inputString) {
try {
return _compactDateFormat.parseStrict(inputString);
} on FormatException {
return null;
}
}
@override
List<String> get narrowWeekdays {
return _longDateFormat.dateSymbols.NARROWWEEKDAYS;
......@@ -576,24 +614,36 @@ class _MaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLocal
);
intl.DateFormat fullYearFormat;
intl.DateFormat compactDateFormat;
intl.DateFormat shortDateFormat;
intl.DateFormat mediumDateFormat;
intl.DateFormat longDateFormat;
intl.DateFormat yearMonthFormat;
intl.DateFormat shortMonthDayFormat;
if (intl.DateFormat.localeExists(localeName)) {
fullYearFormat = intl.DateFormat.y(localeName);
compactDateFormat = intl.DateFormat.yMd(localeName);
shortDateFormat = intl.DateFormat.yMMMd(localeName);
mediumDateFormat = intl.DateFormat.MMMEd(localeName);
longDateFormat = intl.DateFormat.yMMMMEEEEd(localeName);
yearMonthFormat = intl.DateFormat.yMMMM(localeName);
shortMonthDayFormat = intl.DateFormat.MMMd(localeName);
} else if (intl.DateFormat.localeExists(locale.languageCode)) {
fullYearFormat = intl.DateFormat.y(locale.languageCode);
compactDateFormat = intl.DateFormat.yMd(locale.languageCode);
shortDateFormat = intl.DateFormat.yMMMd(locale.languageCode);
mediumDateFormat = intl.DateFormat.MMMEd(locale.languageCode);
longDateFormat = intl.DateFormat.yMMMMEEEEd(locale.languageCode);
yearMonthFormat = intl.DateFormat.yMMMM(locale.languageCode);
shortMonthDayFormat = intl.DateFormat.MMMd(locale.languageCode);
} else {
fullYearFormat = intl.DateFormat.y();
compactDateFormat = intl.DateFormat.yMd();
shortDateFormat = intl.DateFormat.yMMMd();
mediumDateFormat = intl.DateFormat.MMMEd();
longDateFormat = intl.DateFormat.yMMMMEEEEd();
yearMonthFormat = intl.DateFormat.yMMMM();
shortMonthDayFormat = intl.DateFormat.MMMd();
}
intl.NumberFormat decimalFormat;
......@@ -612,9 +662,12 @@ class _MaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLocal
return SynchronousFuture<MaterialLocalizations>(getMaterialTranslation(
locale,
fullYearFormat,
compactDateFormat,
shortDateFormat,
mediumDateFormat,
longDateFormat,
yearMonthFormat,
shortMonthDayFormat,
decimalFormat,
twoDigitZeroPaddedFormat,
));
......
......@@ -19,7 +19,7 @@ void main() {
initialDate = DateTime(2016, DateTime.january, 15);
});
group(DayPicker, () {
group(CalendarDatePicker, () {
final intl.NumberFormat arabicNumbers = intl.NumberFormat('0', 'ar');
final Map<Locale, Map<String, dynamic>> testLocales = <Locale, Map<String, dynamic>>{
// Tests the default.
......@@ -59,13 +59,11 @@ void main() {
final TextDirection textDirection = testLocales[locale]['textDirection'] as TextDirection;
final DateTime baseDate = DateTime(2017, 9, 27);
await _pumpBoilerplate(tester, DayPicker(
selectedDate: baseDate,
currentDate: baseDate,
onChanged: (DateTime newValue) { },
await _pumpBoilerplate(tester, CalendarDatePicker(
initialDate: baseDate,
firstDate: baseDate.subtract(const Duration(days: 90)),
lastDate: baseDate.add(const Duration(days: 90)),
displayedMonth: baseDate,
onDateChanged: (DateTime newValue) {},
), locale: locale, textDirection: textDirection);
expect(find.text(expectedMonthYearHeader), findsOneWidget);
......@@ -126,14 +124,14 @@ void main() {
await tester.tap(find.text('X'));
await tester.pumpAndSettle(const Duration(seconds: 1));
final Element dayPicker = tester.element(find.byType(DayPicker));
final Element picker = tester.element(find.byType(CalendarDatePicker));
expect(
Localizations.localeOf(dayPicker),
Localizations.localeOf(picker),
const Locale('fr', 'CA'),
);
expect(
Directionality.of(dayPicker),
Directionality.of(picker),
TextDirection.ltr,
);
......@@ -169,9 +167,9 @@ void main() {
await tester.tap(find.text('X'));
await tester.pumpAndSettle(const Duration(seconds: 1));
final Element dayPicker = tester.element(find.byType(DayPicker));
final Element picker = tester.element(find.byType(CalendarDatePicker));
expect(
Directionality.of(dayPicker),
Directionality.of(picker),
TextDirection.rtl,
);
......@@ -210,14 +208,14 @@ void main() {
await tester.tap(find.text('X'));
await tester.pumpAndSettle(const Duration(seconds: 1));
final Element dayPicker = tester.element(find.byType(DayPicker));
final Element picker = tester.element(find.byType(CalendarDatePicker));
expect(
Localizations.localeOf(dayPicker),
Localizations.localeOf(picker),
const Locale('fr', 'CA'),
);
expect(
Directionality.of(dayPicker),
Directionality.of(picker),
TextDirection.rtl,
);
......@@ -292,12 +290,16 @@ Future<void> _pumpBoilerplate(
Locale locale = const Locale('en', 'US'),
TextDirection textDirection = TextDirection.ltr,
}) async {
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
child: Localizations(
locale: locale,
delegates: GlobalMaterialLocalizations.delegates,
child: child,
await tester.pumpWidget(MaterialApp(
home: Directionality(
textDirection: TextDirection.ltr,
child: Localizations(
locale: locale,
delegates: GlobalMaterialLocalizations.delegates,
child: Material(
child: child,
),
),
),
));
}
......@@ -15,9 +15,12 @@ class FooMaterialLocalizations extends MaterialLocalizationEn {
) : super(
localeName: localeName.toString(),
fullYearFormat: intl.DateFormat.y(),
compactDateFormat: intl.DateFormat.yMd(),
shortDateFormat: intl.DateFormat.yMMMd(),
mediumDateFormat: intl.DateFormat('E, MMM\u00a0d'),
longDateFormat: intl.DateFormat.yMMMMEEEEd(),
yearMonthFormat: intl.DateFormat.yMMMM(),
shortMonthDayFormat: intl.DateFormat.MMMd(),
decimalFormat: intl.NumberFormat.decimalPattern(),
twoDigitZeroPaddedFormat: intl.NumberFormat('00'),
);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment