fixed selection dialog to close when selecting already selected value
This commit is contained in:
parent
4cbc17cf8f
commit
a7eaf55ed3
3 changed files with 101 additions and 2 deletions
97
lib/widgets/common/aves_radio_list_tile.dart
Normal file
97
lib/widgets/common/aves_radio_list_tile.dart
Normal 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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:aves/widgets/common/aves_radio_list_tile.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ class _AvesSelectionDialogState<T> extends State<AvesSelectionDialog> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildRadioListTile(T value, String title) {
|
Widget _buildRadioListTile(T value, String title) {
|
||||||
return RadioListTile<T>(
|
return AvesRadioListTile<T>(
|
||||||
key: Key(value.toString()),
|
key: Key(value.toString()),
|
||||||
value: value,
|
value: value,
|
||||||
groupValue: _selectedValue,
|
groupValue: _selectedValue,
|
||||||
|
@ -55,6 +56,7 @@ class _AvesSelectionDialogState<T> extends State<AvesSelectionDialog> {
|
||||||
Navigator.pop(context, _selectedValue);
|
Navigator.pop(context, _selectedValue);
|
||||||
setState(() {});
|
setState(() {});
|
||||||
},
|
},
|
||||||
|
reselectable: true,
|
||||||
title: Text(
|
title: Text(
|
||||||
title,
|
title,
|
||||||
softWrap: false,
|
softWrap: false,
|
||||||
|
|
|
@ -102,7 +102,7 @@ class _WelcomePageState extends State<WelcomePage> {
|
||||||
text: 'Allow anonymous crash reporting',
|
text: 'Allow anonymous crash reporting',
|
||||||
),
|
),
|
||||||
LabeledCheckbox(
|
LabeledCheckbox(
|
||||||
key: Key('agree-termsCheckbox'),
|
key: Key('agree-checkbox'),
|
||||||
value: _hasAcceptedTerms,
|
value: _hasAcceptedTerms,
|
||||||
onChanged: (v) => setState(() => _hasAcceptedTerms = v),
|
onChanged: (v) => setState(() => _hasAcceptedTerms = v),
|
||||||
text: 'I agree to the terms and conditions',
|
text: 'I agree to the terms and conditions',
|
||||||
|
|
Loading…
Reference in a new issue