Skip to content

Instantly share code, notes, and snippets.

@Miqueas
Last active June 17, 2024 05:05
Show Gist options
  • Save Miqueas/843849ade4461067c62f607912ad35ec to your computer and use it in GitHub Desktop.
Save Miqueas/843849ade4461067c62f607912ad35ec to your computer and use it in GitHub Desktop.
Custom radio button in Flutter

Custom radio button in Flutter

image

import 'package:flutter/material.dart';
void main() => runApp(
MaterialApp(
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
home: const Scaffold(
body: Center(
child: HomeScreen()
)
)
)
);
enum People {
all,
followed,
subscribed,
}
final class HomeScreen extends StatefulWidget {
const HomeScreen({super.key, this.filter = People.all});
final People filter;
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
late People value;
void _setOption(People newOption) {
Future.delayed(Duration.zero, () {
setState(() => value = newOption);
});
}
@override
void initState() {
super.initState();
value = widget.filter;
}
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RadioButton(
value: People.all,
group: value,
label: 'All',
onChange: _setOption,
),
RadioButton(
value: People.followed,
group: value,
label: 'Follow',
onChange: _setOption,
),
RadioButton(
value: People.subscribed,
group: value,
label: 'Subscribed',
onChange: _setOption,
),
],
),
);
}
}
final class RadioItem extends StatelessWidget {
const RadioItem({
super.key,
required this.active,
this.color = Colors.pinkAccent,
});
final bool active;
final Color color;
@override
Widget build(BuildContext context) {
return AnimatedContainer(
width: 20, height: 20,
duration: const Duration(milliseconds: 100),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: switch (active) {
true => color,
false => Colors.transparent,
},
border: Border.all(
width: switch (active) {
true => 4,
false => 2,
},
color: switch (active) {
true => Theme.of(context).colorScheme.inverseSurface,
false => color,
},
),
),
);
}
}
final class RadioButton<T> extends StatelessWidget {
const RadioButton({
super.key,
required this.value,
required this.group,
required this.label,
required this.onChange,
});
final T value;
final T group;
final String label;
final void Function(T value) onChange;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () => onChange(value),
overlayColor: const WidgetStatePropertyAll(Colors.transparent),
child: Padding(
padding: const EdgeInsets.all(14),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
RadioItem(active: value == group),
const SizedBox(width: 10),
Text(label,
maxLines: 1,
overflow: TextOverflow.ellipsis
),
],
),
)
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment