M3 DatePicker landscape header text style is now TextTheme.headlineSmall (#123732)

M3 DatePicker landscape header text style is now TextTheme.headlineSmall
This commit is contained in:
Hans Muller 2023-03-31 18:14:38 -07:00 committed by GitHub
parent dd7d4b9521
commit 0c365bd9a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 94 additions and 18 deletions

View file

@ -477,21 +477,28 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
final DatePickerThemeData defaults = DatePickerTheme.defaults(context);
final TextTheme textTheme = theme.textTheme;
// Constrain the textScaleFactor to the largest supported value to prevent
// layout issues.
final double textScaleFactor = math.min(MediaQuery.textScaleFactorOf(context), 1.3);
// There's no M3 spec for a landscape layout input (not calendar)
// date picker. To ensure that the date displayed in the input
// date picker's header fits in landscape mode, we override the M3
// default here.
TextStyle? headlineStyle;
if (useMaterial3) {
headlineStyle = datePickerTheme.headerHeadlineStyle ?? defaults.headerHeadlineStyle;
switch (_entryMode.value) {
case DatePickerEntryMode.input:
case DatePickerEntryMode.inputOnly:
if (orientation == Orientation.landscape) {
headlineStyle = textTheme.headlineSmall;
}
case DatePickerEntryMode.calendar:
case DatePickerEntryMode.calendarOnly:
// M3 default is OK.
}
} else {
headlineStyle = orientation == Orientation.landscape ? textTheme.headlineSmall : textTheme.headlineMedium;
}
final Color? headerForegroundColor = datePickerTheme.headerForegroundColor ?? defaults.headerForegroundColor;
final TextStyle? headlineStyle = useMaterial3
? (datePickerTheme.headerHeadlineStyle ?? defaults.headerHeadlineStyle)?.copyWith(
color: headerForegroundColor,
)
// Material2 has support for landscape and the current M3 spec doesn't
// address this layout, so handling it separately here.
: (orientation == Orientation.landscape
? textTheme.headlineSmall?.copyWith(color: headerForegroundColor)
: textTheme.headlineMedium?.copyWith(color: headerForegroundColor));
final String dateText = localizations.formatMediumDate(_selectedDate.value);
headlineStyle = headlineStyle?.copyWith(color: headerForegroundColor);
final Widget actions = Container(
alignment: AlignmentDirectional.centerEnd,
@ -599,13 +606,16 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
? localizations.datePickerHelpText
: localizations.datePickerHelpText.toUpperCase()
),
titleText: dateText,
titleText: localizations.formatMediumDate(_selectedDate.value),
titleStyle: headlineStyle,
orientation: orientation,
isShort: orientation == Orientation.landscape,
entryModeButton: entryModeButton,
);
// Constrain the textScaleFactor to the largest supported value to prevent
// layout issues.
final double textScaleFactor = math.min(MediaQuery.textScaleFactorOf(context), 1.3);
final Size dialogSize = _dialogSize(context) * textScaleFactor;
final DialogTheme dialogTheme = theme.dialogTheme;
return Dialog(
@ -2660,10 +2670,16 @@ class _InputDateRangePickerDialog extends StatelessWidget {
final DatePickerThemeData datePickerTheme = DatePickerTheme.of(context);
final DatePickerThemeData defaults = DatePickerTheme.defaults(context);
// There's no M3 spec for a landscape layout input (not calendar)
// date range picker. To ensure that the date range displayed in the
// input date range picker's header fits in landscape mode, we override
// the M3 default here.
TextStyle? headlineStyle = (orientation == Orientation.portrait)
? datePickerTheme.headerHeadlineStyle ?? defaults.headerHeadlineStyle
: Theme.of(context).textTheme.headlineSmall;
final Color? headerForegroundColor = datePickerTheme.headerForegroundColor ?? defaults.headerForegroundColor;
final TextStyle? headlineStyle = (datePickerTheme.headerHeadlineStyle ?? defaults.headerHeadlineStyle)?.copyWith(
color: headerForegroundColor,
);
headlineStyle = headlineStyle?.copyWith(color: headerForegroundColor);
final String dateText = _formatDateRange(context, selectedStartDate, selectedEndDate, currentDate!);
final String semanticDateText = selectedStartDate != null && selectedEndDate != null

View file

@ -1387,6 +1387,36 @@ void main() {
expect(find.byType(TextField), findsNothing);
});
});
group('Landscape input-only date picker headers use headlineSmall', () {
// Regression test for https://github.com/flutter/flutter/issues/122056
// Common screen size roughly based on a Pixel 1
const Size kCommonScreenSizePortrait = Size(1070, 1770);
const Size kCommonScreenSizeLandscape = Size(1770, 1070);
Future<void> showPicker(WidgetTester tester, Size size) async {
addTearDown(tester.view.reset);
tester.view.physicalSize = size;
tester.view.devicePixelRatio = 1.0;
initialEntryMode = DatePickerEntryMode.input;
await prepareDatePicker(tester, (Future<DateTime?> date) async { }, useMaterial3: true);
}
testWidgets('portrait', (WidgetTester tester) async {
await showPicker(tester, kCommonScreenSizePortrait);
expect(tester.widget<Text>(find.text('Fri, Jan 15')).style?.fontSize, 32);
await tester.tap(find.text('Cancel'));
await tester.pumpAndSettle();
});
testWidgets('landscape', (WidgetTester tester) async {
await showPicker(tester, kCommonScreenSizeLandscape);
expect(tester.widget<Text>(find.text('Fri, Jan 15')).style?.fontSize, 24);
await tester.tap(find.text('Cancel'));
await tester.pumpAndSettle();
});
});
}
class _RestorableDatePickerDialogTestWidget extends StatefulWidget {

View file

@ -108,6 +108,36 @@ void main() {
await callback(range);
}
group('Landscape input-only date picker headers use headlineSmall', () {
// Regression test for https://github.com/flutter/flutter/issues/122056
// Common screen size roughly based on a Pixel 1
const Size kCommonScreenSizePortrait = Size(1070, 1770);
const Size kCommonScreenSizeLandscape = Size(1770, 1070);
Future<void> showPicker(WidgetTester tester, Size size) async {
addTearDown(tester.view.reset);
tester.view.physicalSize = size;
tester.view.devicePixelRatio = 1.0;
initialEntryMode = DatePickerEntryMode.input;
await preparePicker(tester, (Future<DateTimeRange?> range) async { }, useMaterial3: true);
}
testWidgets('portrait', (WidgetTester tester) async {
await showPicker(tester, kCommonScreenSizePortrait);
expect(tester.widget<Text>(find.text('Jan 15 Jan 25, 2016')).style?.fontSize, 32);
await tester.tap(find.text('Cancel'));
await tester.pumpAndSettle();
});
testWidgets('landscape', (WidgetTester tester) async {
await showPicker(tester, kCommonScreenSizeLandscape);
expect(tester.widget<Text>(find.text('Jan 15 Jan 25, 2016')).style?.fontSize, 24);
await tester.tap(find.text('Cancel'));
await tester.pumpAndSettle();
});
});
testWidgets('Save and help text is used', (WidgetTester tester) async {
helpText = 'help';
saveText = 'make it so';