From a7eaf55ed342172ae7bde3483c78698ecefa63ae Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sun, 4 Oct 2020 21:54:41 +0900 Subject: [PATCH] fixed selection dialog to close when selecting already selected value --- lib/widgets/common/aves_radio_list_tile.dart | 97 +++++++++++++++++++ lib/widgets/common/aves_selection_dialog.dart | 4 +- lib/widgets/welcome_page.dart | 2 +- 3 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 lib/widgets/common/aves_radio_list_tile.dart diff --git a/lib/widgets/common/aves_radio_list_tile.dart b/lib/widgets/common/aves_radio_list_tile.dart new file mode 100644 index 000000000..424a26b10 --- /dev/null +++ b/lib/widgets/common/aves_radio_list_tile.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; + +// `RadioListTile` that can trigger `onChanged` on tap when already selected, if `reselectable` is true +class AvesRadioListTile extends StatelessWidget { + final T value; + final T groupValue; + final ValueChanged onChanged; + final bool toggleable; + final bool reselectable; + final Color activeColor; + final Widget title; + final Widget subtitle; + final Widget secondary; + final bool isThreeLine; + final bool dense; + final bool selected; + final ListTileControlAffinity controlAffinity; + final bool autofocus; + + bool get checked => value == groupValue; + + const AvesRadioListTile({ + Key key, + @required this.value, + @required this.groupValue, + @required this.onChanged, + this.toggleable = false, + this.reselectable = false, + this.activeColor, + this.title, + this.subtitle, + this.isThreeLine = false, + this.dense, + this.secondary, + this.selected = false, + this.controlAffinity = ListTileControlAffinity.platform, + this.autofocus = false, + }) : assert(toggleable != null), + assert(isThreeLine != null), + assert(!isThreeLine || subtitle != null), + assert(selected != null), + assert(controlAffinity != null), + assert(autofocus != null), + super(key: key); + + @override + Widget build(BuildContext context) { + final Widget control = Radio( + value: value, + groupValue: groupValue, + onChanged: onChanged, + toggleable: toggleable, + activeColor: activeColor, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + autofocus: autofocus, + ); + Widget leading, trailing; + switch (controlAffinity) { + case ListTileControlAffinity.leading: + case ListTileControlAffinity.platform: + leading = control; + trailing = secondary; + break; + case ListTileControlAffinity.trailing: + leading = secondary; + trailing = control; + break; + } + return MergeSemantics( + child: ListTileTheme.merge( + selectedColor: activeColor ?? Theme.of(context).accentColor, + child: ListTile( + leading: leading, + title: title, + subtitle: subtitle, + trailing: trailing, + isThreeLine: isThreeLine, + dense: dense, + enabled: onChanged != null, + onTap: onChanged != null + ? () { + if (toggleable && checked) { + onChanged(null); + return; + } + if (reselectable || !checked) { + onChanged(value); + } + } + : null, + selected: selected, + autofocus: autofocus, + ), + ), + ); + } +} diff --git a/lib/widgets/common/aves_selection_dialog.dart b/lib/widgets/common/aves_selection_dialog.dart index a8c121f82..1932866ae 100644 --- a/lib/widgets/common/aves_selection_dialog.dart +++ b/lib/widgets/common/aves_selection_dialog.dart @@ -1,3 +1,4 @@ +import 'package:aves/widgets/common/aves_radio_list_tile.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; @@ -46,7 +47,7 @@ class _AvesSelectionDialogState extends State { } Widget _buildRadioListTile(T value, String title) { - return RadioListTile( + return AvesRadioListTile( key: Key(value.toString()), value: value, groupValue: _selectedValue, @@ -55,6 +56,7 @@ class _AvesSelectionDialogState extends State { Navigator.pop(context, _selectedValue); setState(() {}); }, + reselectable: true, title: Text( title, softWrap: false, diff --git a/lib/widgets/welcome_page.dart b/lib/widgets/welcome_page.dart index 09bc45696..bbe6be436 100644 --- a/lib/widgets/welcome_page.dart +++ b/lib/widgets/welcome_page.dart @@ -102,7 +102,7 @@ class _WelcomePageState extends State { text: 'Allow anonymous crash reporting', ), LabeledCheckbox( - key: Key('agree-termsCheckbox'), + key: Key('agree-checkbox'), value: _hasAcceptedTerms, onChanged: (v) => setState(() => _hasAcceptedTerms = v), text: 'I agree to the terms and conditions',