Unverified Commit 49be0586 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Fix dayPeriodColor handling of non-MaterialStateColors (#139845)

## Description

This fixes the handling of `dayPeriodColor` on the `TimePicker` so that if it's a non-`MaterialStateColor`, it only applies the color to the selected state, but otherwise uses the given `MaterialStateColor` to get custom behavior.

## Related Issues
 - Fixes https://github.com/flutter/flutter/issues/139445

## Tests
 - Added tests for both non-`MaterialStateColor` and `MaterialStateColor` cases.
parent 8a96fb33
...@@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart'; ...@@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'button_style.dart'; import 'button_style.dart';
import 'colors.dart';
import 'input_decorator.dart'; import 'input_decorator.dart';
import 'material_state.dart'; import 'material_state.dart';
import 'theme.dart'; import 'theme.dart';
...@@ -43,7 +44,7 @@ class TimePickerThemeData with Diagnosticable { ...@@ -43,7 +44,7 @@ class TimePickerThemeData with Diagnosticable {
this.cancelButtonStyle, this.cancelButtonStyle,
this.confirmButtonStyle, this.confirmButtonStyle,
this.dayPeriodBorderSide, this.dayPeriodBorderSide,
this.dayPeriodColor, Color? dayPeriodColor,
this.dayPeriodShape, this.dayPeriodShape,
this.dayPeriodTextColor, this.dayPeriodTextColor,
this.dayPeriodTextStyle, this.dayPeriodTextStyle,
...@@ -61,7 +62,7 @@ class TimePickerThemeData with Diagnosticable { ...@@ -61,7 +62,7 @@ class TimePickerThemeData with Diagnosticable {
this.inputDecorationTheme, this.inputDecorationTheme,
this.padding, this.padding,
this.shape, this.shape,
}); }) : _dayPeriodColor = dayPeriodColor;
/// The background color of a time picker. /// The background color of a time picker.
/// ///
...@@ -102,7 +103,21 @@ class TimePickerThemeData with Diagnosticable { ...@@ -102,7 +103,21 @@ class TimePickerThemeData with Diagnosticable {
/// brightness is [Brightness.dark]. /// brightness is [Brightness.dark].
/// If the segment is not selected, [Colors.transparent] is used to allow the /// If the segment is not selected, [Colors.transparent] is used to allow the
/// [Dialog]'s color to be used. /// [Dialog]'s color to be used.
final Color? dayPeriodColor; Color? get dayPeriodColor {
if (_dayPeriodColor == null || _dayPeriodColor is MaterialStateColor) {
return _dayPeriodColor;
}
return MaterialStateColor.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return _dayPeriodColor;
}
// The unselected day period should match the overall picker dialog color.
// Making it transparent enables that without being redundant and allows
// the optional elevation overlay for dark mode to be visible.
return Colors.transparent;
});
}
final Color? _dayPeriodColor;
/// The shape of the day period that the time picker uses. /// The shape of the day period that the time picker uses.
/// ///
......
...@@ -18,7 +18,7 @@ void main() { ...@@ -18,7 +18,7 @@ void main() {
expect(identical(TimePickerThemeData.lerp(data, data, 0.5), data), true); expect(identical(TimePickerThemeData.lerp(data, data, 0.5), data), true);
}); });
test('TimePickerThemeData null fields by default', () { test('TimePickerThemeData has null fields by default', () {
const TimePickerThemeData timePickerTheme = TimePickerThemeData(); const TimePickerThemeData timePickerTheme = TimePickerThemeData();
expect(timePickerTheme.backgroundColor, null); expect(timePickerTheme.backgroundColor, null);
expect(timePickerTheme.cancelButtonStyle, null); expect(timePickerTheme.cancelButtonStyle, null);
...@@ -64,7 +64,7 @@ void main() { ...@@ -64,7 +64,7 @@ void main() {
cancelButtonStyle: ButtonStyle(foregroundColor: MaterialStatePropertyAll<Color>(Color(0xfffffff1))), cancelButtonStyle: ButtonStyle(foregroundColor: MaterialStatePropertyAll<Color>(Color(0xfffffff1))),
confirmButtonStyle: ButtonStyle(foregroundColor: MaterialStatePropertyAll<Color>(Color(0xfffffff2))), confirmButtonStyle: ButtonStyle(foregroundColor: MaterialStatePropertyAll<Color>(Color(0xfffffff2))),
dayPeriodBorderSide: BorderSide(color: Color(0xfffffff3)), dayPeriodBorderSide: BorderSide(color: Color(0xfffffff3)),
dayPeriodColor: Color(0xfffffff4), dayPeriodColor: Color(0x00000000),
dayPeriodShape: RoundedRectangleBorder( dayPeriodShape: RoundedRectangleBorder(
side: BorderSide(color: Color(0xfffffff5)), side: BorderSide(color: Color(0xfffffff5)),
), ),
...@@ -102,7 +102,7 @@ void main() { ...@@ -102,7 +102,7 @@ void main() {
'cancelButtonStyle: ButtonStyle#00000(foregroundColor: MaterialStatePropertyAll(Color(0xfffffff1)))', 'cancelButtonStyle: ButtonStyle#00000(foregroundColor: MaterialStatePropertyAll(Color(0xfffffff1)))',
'confirmButtonStyle: ButtonStyle#00000(foregroundColor: MaterialStatePropertyAll(Color(0xfffffff2)))', 'confirmButtonStyle: ButtonStyle#00000(foregroundColor: MaterialStatePropertyAll(Color(0xfffffff2)))',
'dayPeriodBorderSide: BorderSide(color: Color(0xfffffff3))', 'dayPeriodBorderSide: BorderSide(color: Color(0xfffffff3))',
'dayPeriodColor: Color(0xfffffff4)', 'dayPeriodColor: Color(0x00000000)',
'dayPeriodShape: RoundedRectangleBorder(BorderSide(color: Color(0xfffffff5)), BorderRadius.zero)', 'dayPeriodShape: RoundedRectangleBorder(BorderSide(color: Color(0xfffffff5)), BorderRadius.zero)',
'dayPeriodTextColor: Color(0xfffffff6)', 'dayPeriodTextColor: Color(0xfffffff6)',
'dayPeriodTextStyle: TextStyle(inherit: true, color: Color(0xfffffff7))', 'dayPeriodTextStyle: TextStyle(inherit: true, color: Color(0xfffffff7))',
...@@ -764,6 +764,41 @@ void main() { ...@@ -764,6 +764,41 @@ void main() {
final InputDecoration hourDecoration = _textField(tester, '7').decoration!; final InputDecoration hourDecoration = _textField(tester, '7').decoration!;
expect(hourDecoration.fillColor?.value, timePickerTheme.hourMinuteColor?.value); expect(hourDecoration.fillColor?.value, timePickerTheme.hourMinuteColor?.value);
}); });
testWidgetsWithLeakTracking('Time picker dayPeriodColor does the right thing with non-MaterialStateColor', (WidgetTester tester) async {
final TimePickerThemeData timePickerTheme = _timePickerTheme().copyWith(dayPeriodColor: Colors.red);
final ThemeData theme = ThemeData(timePickerTheme: timePickerTheme);
await tester.pumpWidget(_TimePickerLauncher(themeData: theme, entryMode: TimePickerEntryMode.input));
await tester.tap(find.text('X'));
await tester.pumpAndSettle(const Duration(seconds: 1));
final Material amMaterial = _textMaterial(tester, 'AM');
expect(amMaterial.color, Colors.red);
final Material pmMaterial = _textMaterial(tester, 'PM');
expect(pmMaterial.color, Colors.transparent);
});
testWidgetsWithLeakTracking('Time picker dayPeriodColor does the right thing with MaterialStateColor', (WidgetTester tester) async {
final MaterialStateColor testColor = MaterialStateColor.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return Colors.green;
}
return Colors.blue;
});
final TimePickerThemeData timePickerTheme = _timePickerTheme().copyWith(dayPeriodColor: testColor);
final ThemeData theme = ThemeData(timePickerTheme: timePickerTheme);
await tester.pumpWidget(_TimePickerLauncher(themeData: theme, entryMode: TimePickerEntryMode.input));
await tester.tap(find.text('X'));
await tester.pumpAndSettle(const Duration(seconds: 1));
final Material amMaterial = _textMaterial(tester, 'AM');
expect(amMaterial.color, Colors.green);
final Material pmMaterial = _textMaterial(tester, 'PM');
expect(pmMaterial.color, Colors.blue);
});
} }
final Color _selectedColor = Colors.green[100]!; final Color _selectedColor = Colors.green[100]!;
......
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