Unverified Commit 55558367 authored by Polina Cherkasova's avatar Polina Cherkasova Committed by GitHub

Day picker should dispose created MaterialStatesController's. (#133884)

Fixes https://github.com/flutter/flutter/issues/133862
parent 3f4ee3fb
...@@ -868,6 +868,10 @@ class _DayPickerState extends State<_DayPicker> { ...@@ -868,6 +868,10 @@ class _DayPickerState extends State<_DayPicker> {
/// List of [FocusNode]s, one for each day of the month. /// List of [FocusNode]s, one for each day of the month.
late List<FocusNode> _dayFocusNodes; late List<FocusNode> _dayFocusNodes;
// TODO(polina-c): a cleaner solution is to create separate statefull widget for a day.
// https://github.com/flutter/flutter/issues/134323
final Map<int, MaterialStatesController> _statesControllers = <int, MaterialStatesController>{};
@override @override
void initState() { void initState() {
super.initState(); super.initState();
...@@ -893,6 +897,9 @@ class _DayPickerState extends State<_DayPicker> { ...@@ -893,6 +897,9 @@ class _DayPickerState extends State<_DayPicker> {
for (final FocusNode node in _dayFocusNodes) { for (final FocusNode node in _dayFocusNodes) {
node.dispose(); node.dispose();
} }
for (final MaterialStatesController controller in _statesControllers.values) {
controller.dispose();
}
super.dispose(); super.dispose();
} }
...@@ -973,6 +980,9 @@ class _DayPickerState extends State<_DayPicker> { ...@@ -973,6 +980,9 @@ class _DayPickerState extends State<_DayPicker> {
if (isSelectedDay) MaterialState.selected, if (isSelectedDay) MaterialState.selected,
}; };
final MaterialStatesController statesController = _statesControllers.putIfAbsent(day, () => MaterialStatesController());
statesController.value = states;
final Color? dayForegroundColor = resolve<Color?>((DatePickerThemeData? theme) => isToday ? theme?.todayForegroundColor : theme?.dayForegroundColor, states); final Color? dayForegroundColor = resolve<Color?>((DatePickerThemeData? theme) => isToday ? theme?.todayForegroundColor : theme?.dayForegroundColor, states);
final Color? dayBackgroundColor = resolve<Color?>((DatePickerThemeData? theme) => isToday ? theme?.todayBackgroundColor : theme?.dayBackgroundColor, states); final Color? dayBackgroundColor = resolve<Color?>((DatePickerThemeData? theme) => isToday ? theme?.todayBackgroundColor : theme?.dayBackgroundColor, states);
final MaterialStateProperty<Color?> dayOverlayColor = MaterialStateProperty.resolveWith<Color?>( final MaterialStateProperty<Color?> dayOverlayColor = MaterialStateProperty.resolveWith<Color?>(
...@@ -1008,7 +1018,7 @@ class _DayPickerState extends State<_DayPicker> { ...@@ -1008,7 +1018,7 @@ class _DayPickerState extends State<_DayPicker> {
focusNode: _dayFocusNodes[day - 1], focusNode: _dayFocusNodes[day - 1],
onTap: () => widget.onChanged(dayToBuild), onTap: () => widget.onChanged(dayToBuild),
radius: _dayPickerRowHeight / 2 + 4, radius: _dayPickerRowHeight / 2 + 4,
statesController: MaterialStatesController(states), statesController: statesController,
overlayColor: dayOverlayColor, overlayColor: dayOverlayColor,
child: Semantics( child: Semantics(
// We want the day of month to be spoken first irrespective of the // We want the day of month to be spoken first irrespective of the
......
...@@ -516,6 +516,30 @@ void main() { ...@@ -516,6 +516,30 @@ void main() {
expect(find.text('2017'), findsNothing); expect(find.text('2017'), findsNothing);
}); });
testWidgets('Selecting disabled date does not change current selection', (WidgetTester tester) async {
DateTime day(int day) => DateTime(2020, DateTime.may, day);
DateTime selection = day(2);
await tester.pumpWidget(calendarDatePicker(
initialDate: selection,
firstDate: day(2),
lastDate: day(3),
onDateChanged: (DateTime date) {
selection = date;
},
));
await tester.tap(find.text('3'));
await tester.pumpAndSettle();
expect(selection, day(3));
await tester.tap(find.text('4'));
await tester.pumpAndSettle();
expect(selection, day(3));
await tester.tap(find.text('5'));
await tester.pumpAndSettle();
expect(selection, day(3));
});
for (final bool useMaterial3 in <bool>[false, true]) { for (final bool useMaterial3 in <bool>[false, true]) {
testWidgets('Updates to initialDate parameter are not reflected in the state (useMaterial3=$useMaterial3)', (WidgetTester tester) async { testWidgets('Updates to initialDate parameter are not reflected in the state (useMaterial3=$useMaterial3)', (WidgetTester tester) async {
final Key pickerKey = UniqueKey(); final Key pickerKey = UniqueKey();
......
...@@ -8,7 +8,6 @@ import 'package:flutter/foundation.dart'; ...@@ -8,7 +8,6 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
...@@ -173,16 +172,11 @@ void main() { ...@@ -173,16 +172,11 @@ void main() {
}, useMaterial3: theme.useMaterial3); }, useMaterial3: theme.useMaterial3);
}); });
testWidgetsWithLeakTracking('Material3 uses sentence case labels', (WidgetTester tester) async { testWidgets('Material3 uses sentence case labels', (WidgetTester tester) async {
await prepareDatePicker(tester, (Future<DateTime?> date) async { await prepareDatePicker(tester, (Future<DateTime?> date) async {
expect(find.text('Select date'), findsOneWidget); expect(find.text('Select date'), findsOneWidget);
}, useMaterial3: true); }, useMaterial3: true);
}, });
leakTrackingTestConfig: const LeakTrackingTestConfig(
// TODO(polina-c): remove after fixing
// https://github.com/flutter/flutter/issues/133862
allowAllNotDisposed: true,
));
testWidgets('Cancel, confirm, and help text is used', (WidgetTester tester) async { testWidgets('Cancel, confirm, and help text is used', (WidgetTester tester) async {
cancelText = 'nope'; cancelText = 'nope';
......
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