From f44f43358f044fcd6e2b6f3834d64d747bca7941 Mon Sep 17 00:00:00 2001 From: xubaolin Date: Tue, 25 Aug 2020 06:31:33 +0800 Subject: [PATCH] Fix bug when tapping ListTitle with CheckboxListTile tristate enable (#63925) * fix bug when tap ListTitle when tristate enable #63846 * fix bug when tap ListTitle when tristate enable #63846 * code style * improve the unit test case * bow to convention --- packages/flutter/lib/src/cupertino/theme.dart | 2 +- .../lib/src/material/checkbox_list_tile.dart | 17 ++++++- .../lib/src/physics/spring_simulation.dart | 2 +- .../src/widgets/single_child_scroll_view.dart | 2 +- .../material/checkbox_list_tile_test.dart | 45 +++++++++++++++++-- 5 files changed, 61 insertions(+), 7 deletions(-) diff --git a/packages/flutter/lib/src/cupertino/theme.dart b/packages/flutter/lib/src/cupertino/theme.dart index 164824a71ec..f475e5c7f7f 100644 --- a/packages/flutter/lib/src/cupertino/theme.dart +++ b/packages/flutter/lib/src/cupertino/theme.dart @@ -98,7 +98,7 @@ class CupertinoTheme extends StatelessWidget { @override Widget build(BuildContext context) { - return _InheritedCupertinoTheme( + return _InheritedCupertinoTheme( theme: this, child: IconTheme( data: CupertinoIconThemeData(color: data.primaryColor), diff --git a/packages/flutter/lib/src/material/checkbox_list_tile.dart b/packages/flutter/lib/src/material/checkbox_list_tile.dart index b74f210ed9c..a62376e8ad7 100644 --- a/packages/flutter/lib/src/material/checkbox_list_tile.dart +++ b/packages/flutter/lib/src/material/checkbox_list_tile.dart @@ -382,6 +382,21 @@ class CheckboxListTile extends StatelessWidget { /// If tristate is false (the default), [value] must not be null. final bool tristate; + void _handleValueChange() { + assert(onChanged != null); + switch (value) { + case false: + onChanged(true); + break; + case true: + onChanged(tristate ? null : false); + break; + default: // case null: + onChanged(false); + break; + } + } + @override Widget build(BuildContext context) { final Widget control = Checkbox( @@ -416,7 +431,7 @@ class CheckboxListTile extends StatelessWidget { isThreeLine: isThreeLine, dense: dense, enabled: onChanged != null, - onTap: onChanged != null ? () { onChanged(!value); } : null, + onTap: onChanged != null ? _handleValueChange : null, selected: selected, autofocus: autofocus, contentPadding: contentPadding, diff --git a/packages/flutter/lib/src/physics/spring_simulation.dart b/packages/flutter/lib/src/physics/spring_simulation.dart index ff5b7117e41..7d26609ef76 100644 --- a/packages/flutter/lib/src/physics/spring_simulation.dart +++ b/packages/flutter/lib/src/physics/spring_simulation.dart @@ -277,7 +277,7 @@ class _UnderdampedSolution implements _SpringSolution { final double power = math.pow(math.e, _r * time) as double; final double cosine = math.cos(_w * time); final double sine = math.sin(_w * time); - return power * (_c2 * _w * cosine - _c1 * _w * sine) + + return power * (_c2 * _w * cosine - _c1 * _w * sine) + _r * power * (_c2 * sine + _c1 * cosine); } diff --git a/packages/flutter/lib/src/widgets/single_child_scroll_view.dart b/packages/flutter/lib/src/widgets/single_child_scroll_view.dart index 4c2cda44a6f..17d08c399ac 100644 --- a/packages/flutter/lib/src/widgets/single_child_scroll_view.dart +++ b/packages/flutter/lib/src/widgets/single_child_scroll_view.dart @@ -573,7 +573,7 @@ class _RenderSingleChildViewport extends RenderBox with RenderObjectWithChildMix bool _shouldClipAtPaintOffset(Offset paintOffset) { assert(child != null); - return paintOffset.dx < 0 || + return paintOffset.dx < 0 || paintOffset.dy < 0 || paintOffset.dx + child.size.width > size.width || paintOffset.dy + child.size.height > size.height; diff --git a/packages/flutter/test/material/checkbox_list_tile_test.dart b/packages/flutter/test/material/checkbox_list_tile_test.dart index f5913d2fd3f..45487ee5e29 100644 --- a/packages/flutter/test/material/checkbox_list_tile_test.dart +++ b/packages/flutter/test/material/checkbox_list_tile_test.dart @@ -148,7 +148,8 @@ void main() { }); testWidgets('CheckboxListTile tristate test', (WidgetTester tester) async { - bool _value; + bool _value = false; + bool _tristate = false; await tester.pumpWidget( Material( @@ -157,7 +158,7 @@ void main() { return wrap( child: CheckboxListTile( title: const Text('Title'), - tristate: true, + tristate: _tristate, value: _value, onChanged: (bool value) { setState(() { @@ -171,12 +172,33 @@ void main() { ), ); - expect(tester.widget(find.byType(Checkbox)).value, null); + expect(tester.widget(find.byType(Checkbox)).value, false); + + // Tap the checkbox when tristate is disabled. + await tester.tap(find.byType(Checkbox)); + await tester.pumpAndSettle(); + expect(_value, true); await tester.tap(find.byType(Checkbox)); await tester.pumpAndSettle(); expect(_value, false); + // Tap the listTile when tristate is disabled. + await tester.tap(find.byType(ListTile)); + await tester.pumpAndSettle(); + expect(_value, true); + + await tester.tap(find.byType(ListTile)); + await tester.pumpAndSettle(); + expect(_value, false); + + // Enable tristate + _tristate = true; + await tester.pumpAndSettle(); + + expect(tester.widget(find.byType(Checkbox)).value, false); + + // Tap the checkbox when tristate is enabled. await tester.tap(find.byType(Checkbox)); await tester.pumpAndSettle(); expect(_value, true); @@ -184,5 +206,22 @@ void main() { await tester.tap(find.byType(Checkbox)); await tester.pumpAndSettle(); expect(_value, null); + + await tester.tap(find.byType(Checkbox)); + await tester.pumpAndSettle(); + expect(_value, false); + + // Tap the listTile when tristate is enabled. + await tester.tap(find.byType(ListTile)); + await tester.pumpAndSettle(); + expect(_value, true); + + await tester.tap(find.byType(ListTile)); + await tester.pumpAndSettle(); + expect(_value, null); + + await tester.tap(find.byType(ListTile)); + await tester.pumpAndSettle(); + expect(_value, false); }); }