Last active
July 10, 2023 04:06
-
-
Save CoderNamedHendrick/f599965d1f21fca6ff54f673660c132f to your computer and use it in GitHub Desktop.
Radio button group
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: form_widget_demo | |
description: A new Flutter project. | |
publish_to: 'none' # Remove this line if you wish to publish to pub.dev | |
version: 1.0.0+1 | |
environment: | |
sdk: '>=3.0.5 <4.0.0' | |
dependencies: | |
flutter: | |
sdk: flutter | |
cupertino_icons: ^1.0.2 | |
image_picker: ^1.0.0 | |
dev_dependencies: | |
flutter_test: | |
sdk: flutter | |
flutter_lints: ^2.0.0 | |
flutter: | |
uses-material-design: true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: <Widget>[ | |
ImagePickerFormField( | |
validator: (imageFile) { | |
if (imageFile == null) return 'Please select an image'; | |
return null; | |
}, | |
), | |
const SizedBox(height: 12), | |
RadioButtonGroup(), | |
const SizedBox(height: 20), | |
ElevatedButton( | |
onPressed: () { | |
final isValid = formKey.currentState!.validate(); | |
if (isValid) { | |
ScaffoldMessenger.of(context).showSnackBar( | |
const SnackBar( | |
backgroundColor: Colors.green, | |
content: Text( | |
'Form is valid', | |
style: TextStyle(color: Colors.white), | |
), | |
), | |
); | |
} | |
}, | |
child: const Text('Validate Form'), | |
) | |
], | |
), |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: <Widget>[ | |
ImagePickerFormField( | |
validator: (imageFile) { | |
if (imageFile == null) return 'Please select an image'; | |
return null; | |
}, | |
), | |
const SizedBox(height: 12), | |
RadioButtonFormGroup( | |
validator: (input) { | |
if (input == null) return 'Please select an option'; | |
return null; | |
}, | |
), | |
const SizedBox(height: 20), | |
ElevatedButton( | |
onPressed: () { | |
final isValid = formKey.currentState!.validate(); | |
if (isValid) { | |
ScaffoldMessenger.of(context).showSnackBar( | |
const SnackBar( | |
backgroundColor: Colors.green, | |
content: Text( | |
'Form is valid', | |
style: TextStyle(color: Colors.white), | |
), | |
), | |
); | |
} | |
}, | |
child: const Text('Validate Form'), | |
) | |
], | |
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum RadioInput { | |
text('Text'), | |
widget('Widget'), | |
flutter('Flutter'); | |
const RadioInput(this.title); | |
final String title; | |
} | |
class RadioButtonFormGroup extends FormField<RadioInput?> { | |
RadioButtonFormGroup({ | |
super.key, | |
RadioGroupInputController? controller, | |
ValueChanged<RadioInput?>? onChanged, | |
super.validator, | |
super.autovalidateMode, | |
}) : super( | |
initialValue: controller?.value, | |
builder: (state) { | |
void onChangedHandler(RadioInput? value) { | |
state.didChange(value); | |
if (onChanged != null) { | |
onChanged(value); | |
} | |
} | |
return UnmanagedRestorationScope( | |
bucket: state.bucket, | |
child: Padding( | |
padding: const EdgeInsets.symmetric(vertical: 8.0), | |
child: Column( | |
mainAxisSize: MainAxisSize.min, | |
crossAxisAlignment: CrossAxisAlignment.stretch, | |
children: [ | |
RadioButtonGroup( | |
controller: controller, | |
onChanged: onChangedHandler, | |
fillColor: state.hasError ? Colors.red : null, | |
), | |
if (state.hasError) ...[ | |
Text( | |
state.errorText!, | |
style: const TextStyle(fontSize: 15, color: Colors.red), | |
), | |
], | |
], | |
), | |
), | |
); | |
}, | |
); | |
} | |
class RadioButtonGroup extends StatefulWidget { | |
const RadioButtonGroup({ | |
Key? key, | |
this.controller, | |
this.onChanged, | |
this.fillColor, | |
}) : super(key: key); | |
final RadioGroupInputController? controller; | |
final ValueChanged<RadioInput?>? onChanged; | |
final Color? fillColor; | |
@override | |
State<RadioButtonGroup> createState() => _RadioButtonGroupState(); | |
} | |
class _RadioButtonGroupState extends State<RadioButtonGroup> { | |
late RadioGroupInputController controller; | |
@override | |
void initState() { | |
super.initState(); | |
controller = widget.controller ?? RadioGroupInputController(); | |
controller.addListener(() { | |
widget.onChanged?.call(controller.value); | |
}); | |
} | |
@override | |
void didUpdateWidget(covariant RadioButtonGroup oldWidget) { | |
super.didUpdateWidget(oldWidget); | |
if (oldWidget.controller != widget.controller) { | |
controller = widget.controller ?? RadioGroupInputController(); | |
} | |
} | |
@override | |
void dispose() { | |
if (widget.controller == null) controller.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return ValueListenableBuilder( | |
valueListenable: controller, | |
builder: (_, radioGroupValue, __) => Column( | |
mainAxisSize: MainAxisSize.min, | |
children: RadioInput.values | |
.map((e) => RadioListTile( | |
value: e, | |
groupValue: radioGroupValue, | |
fillColor: switch (widget.fillColor) { | |
final color? => MaterialStateProperty.all(color), | |
_ => null, | |
}, | |
title: Text(e.title), | |
onChanged: (value) { | |
controller.input = value; | |
}, | |
)) | |
.toList(), | |
), | |
); | |
} | |
} | |
class RadioGroupInputController extends ValueNotifier<RadioInput?> { | |
RadioGroupInputController({RadioInput? initialValue}) : super(initialValue); | |
String get title => value?.title ?? ''; | |
set input(RadioInput? newInput) { | |
if (newInput == value) null; | |
value = newInput; | |
notifyListeners(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment