fixed selection dialog to close when selecting already selected value

This commit is contained in:
Thibault Deckers 2020-10-04 21:54:41 +09:00
parent 4cbc17cf8f
commit a7eaf55ed3
3 changed files with 101 additions and 2 deletions

View file

@ -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<T> extends StatelessWidget {
final T value;
final T groupValue;
final ValueChanged<T> 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<T>(
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,
),
),
);
}
}

View file

@ -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<T> extends State<AvesSelectionDialog> {
}
Widget _buildRadioListTile(T value, String title) {
return RadioListTile<T>(
return AvesRadioListTile<T>(
key: Key(value.toString()),
value: value,
groupValue: _selectedValue,
@ -55,6 +56,7 @@ class _AvesSelectionDialogState<T> extends State<AvesSelectionDialog> {
Navigator.pop(context, _selectedValue);
setState(() {});
},
reselectable: true,
title: Text(
title,
softWrap: false,

View file

@ -102,7 +102,7 @@ class _WelcomePageState extends State<WelcomePage> {
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',