Tile
Select Tile Group
A group of tiles that allow users to make a selection from a set of options.
For desktop, a select group is generally recommended over this.
enum Sidebar { recents, home, applications }
FSelectTileGroup<Sidebar>(
control: const FMultiValueControl.managed(initial: {Sidebar.recents}),
label: const Text('Sidebar'),
description: const Text('These will be shown in the sidebar.'),
children: const [
FSelectTile(title: Text('Recents'), suffix: Icon(FIcons.timer), value: Sidebar.recents),
FSelectTile(title: Text('Home'), suffix: Icon(FIcons.house), value: Sidebar.home),
FSelectTile(title: Text('Applications'), suffix: Icon(FIcons.appWindowMac), value: Sidebar.applications),
],
);CLI
To generate and customize this style:
dart run forui style create select-tile-groupUsage
FSelectTileGroup(...)
FSelectTileGroup<Value>(
children: [
FSelectTile(title: const Text('Option 1'), value: Value.option1),
],
control: FMultiValueControl.managed(initial: {Value.option1}),
scrollController: ScrollController(),
style: FTileGroupStyle(...),
cacheExtent: 100,
maxHeight: 200,
dragStartBehavior: DragStartBehavior.start,
physics: const ClampingScrollPhysics(),
divider: FItemDivider.indented,
label: const Text('Sidebar'),
description: const Text('Select the items you want to display in the sidebar.'),
semanticsLabel: 'Sidebar',
errorBuilder: (context, error) => Text(error),
onSaved: (values) {},
onReset: () {},
validator: (values) => values?.isEmpty ?? true ? 'Select an item' : null,
forceErrorText: null,
enabled: true,
autovalidateMode: AutovalidateMode.disabled,
);FSelectTileGroup.builder(...)
FSelectTileGroup<int>.builder(
tileBuilder: (context, index) => FSelectTile(title: Text('Tile $index'), value: index),
count: 100,
control: FMultiValueControl.managed(initial: {1}),
scrollController: ScrollController(),
style: FTileGroupStyle(...),
cacheExtent: 100,
maxHeight: 200,
dragStartBehavior: DragStartBehavior.start,
physics: const ClampingScrollPhysics(),
divider: FItemDivider.indented,
label: const Text('Settings'),
description: const Text('Personalize your experience'),
semanticsLabel: 'Settings',
errorBuilder: (context, error) => Text(error),
onSaved: (values) {},
onReset: () {},
validator: (values) => values?.isEmpty ?? true ? 'Select an item' : null,
forceErrorText: null,
enabled: true,
autovalidateMode: AutovalidateMode.disabled,
);Examples
Behavior
Scrollable
enum Sidebar { recents, home, applications }
FSelectTileGroup<Sidebar>(
control: const FMultiValueControl.managed(initial: {Sidebar.recents}),
label: const Text('Sidebar'),
description: const Text('These will be shown in the sidebar.'),
maxHeight: 100,
children: const [
FSelectTile(title: Text('Recents'), suffix: Icon(FIcons.timer), value: Sidebar.recents),
FSelectTile(title: Text('Home'), suffix: Icon(FIcons.house), value: Sidebar.home),
FSelectTile(title: Text('Applications'), suffix: Icon(FIcons.appWindowMac), value: Sidebar.applications),
],
);Lazy Scrollable
FSelectTileGroup<int>.builder(
control: const FMultiValueControl.managed(initial: {1}),
label: const Text('Applicable values'),
maxHeight: 200,
tileBuilder: (context, index) => FSelectTile(title: Text('Tile $index'), value: index),
);Multi-value Form
enum Language { dart, java, rust, python }
class MultiValueForm extends StatefulWidget {
const MultiValueForm({super.key});
@override
State<MultiValueForm> createState() => _MultiValueFormState();
}
class _MultiValueFormState extends State<MultiValueForm> {
final _key = GlobalKey<FormState>();
@override
Widget build(BuildContext context) => Form(
key: _key,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 20,
children: [
FSelectTileGroup<Language>(
label: const Text('Favorite Languages'),
description: const Text('Your favorite language.'),
validator: (values) => (values?.isEmpty ?? true) ? 'Please select at least one language.' : null,
children: const [
FSelectTile(title: Text('Dart'), value: Language.dart),
FSelectTile(title: Text('Java'), value: Language.java),
FSelectTile(title: Text('Rust'), value: Language.rust),
FSelectTile(title: Text('Python'), value: Language.python),
],
),
FButton(
child: const Text('Save'),
onPress: () {
if (!_key.currentState!.validate()) {
// Handle errors here.
return;
}
_key.currentState!.save();
// Do something.
},
),
],
),
);
}Radio Form
enum Notification { all, direct, nothing }
class RadioForm extends StatefulWidget {
const RadioForm({super.key});
@override
State<RadioForm> createState() => _RadioFormState();
}
class _RadioFormState extends State<RadioForm> {
final _key = GlobalKey<FormState>();
final _controller = FMultiValueNotifier<Notification>.radio();
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) => Form(
key: _key,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 20,
children: [
FSelectTileGroup<Notification>(
control: FMultiValueControl.managed(controller: _controller),
label: const Text('Notifications'),
description: const Text('Select the notifications.'),
validator: (values) => values?.isEmpty ?? true ? 'Please select a value.' : null,
children: const [
FSelectTile(title: Text('All new messages'), value: Notification.all),
FSelectTile(title: Text('Direct messages and mentions'), value: Notification.direct),
FSelectTile(title: Text('Nothing'), value: Notification.nothing),
],
),
FButton(
child: const Text('Save'),
onPress: () {
if (!_key.currentState!.validate()) {
// Handle errors here.
return;
}
_key.currentState!.save();
// Do something.
},
),
],
),
);
}Appearance
Custom Icons
FSelectTileGroup<String>(
control: const FMultiValueControl.managedRadio(),
label: const Text('Settings'),
children: const [
FSelectTile.suffix(prefix: Icon(FIcons.list), title: Text('List View'), value: 'List'),
FSelectTile.suffix(prefix: Icon(FIcons.layoutGrid), title: Text('Grid View'), value: 'Grid'),
],
);Full Divider
enum Sidebar { recents, home, applications }
FSelectTileGroup<Sidebar>(
control: const FMultiValueControl.managed(initial: {Sidebar.recents}),
divider: FItemDivider.full,
label: const Text('Sidebar'),
description: const Text('These will be shown in the sidebar.'),
children: const [
FSelectTile(title: Text('Recents'), suffix: Icon(FIcons.timer), value: Sidebar.recents),
FSelectTile(title: Text('Home'), suffix: Icon(FIcons.house), value: Sidebar.home),
FSelectTile(title: Text('Applications'), suffix: Icon(FIcons.appWindowMac), value: Sidebar.applications),
],
);No Divider
enum Sidebar { recents, home, applications }
FSelectTileGroup<Sidebar>(
control: const FMultiValueControl.managed(initial: {Sidebar.recents}),
divider: FItemDivider.none,
label: const Text('Sidebar'),
description: const Text('These will be shown in the sidebar.'),
children: const [
FSelectTile(title: Text('Recents'), suffix: Icon(FIcons.timer), value: Sidebar.recents),
FSelectTile(title: Text('Home'), suffix: Icon(FIcons.house), value: Sidebar.home),
FSelectTile(title: Text('Applications'), suffix: Icon(FIcons.appWindowMac), value: Sidebar.applications),
],
);