Skip to content

Instantly share code, notes, and snippets.

@luangong
Last active March 10, 2024 14:54
Show Gist options
  • Save luangong/035eac0d9b387b47199ab012cde30d91 to your computer and use it in GitHub Desktop.
Save luangong/035eac0d9b387b47199ab012cde30d91 to your computer and use it in GitHub Desktop.
CupertinoSelectFormFieldRow
import 'package:flutter/cupertino.dart';
void main() => runApp(const MyApp());
enum Direction {
up('UP'), down('DOWN'), left('LEFT'), right('RIGHT');
final String title;
const Direction(this.title);
@override
String toString() => title;
}
enum PhoneType {
mobile('Mobile'), home('Home');
final String title;
const PhoneType(this.title);
@override
String toString() => title;
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return CupertinoApp(
debugShowCheckedModeBanner: false,
theme: CupertinoThemeData(
scaffoldBackgroundColor: CupertinoColors.systemGroupedBackground,
barBackgroundColor: CupertinoColors.secondarySystemBackground,
),
home: CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Home'),
),
child: CupertinoListSection(
hasLeading: false,
children: [
// CupertinoTextFormFieldRow(
// prefix: SizedBox(width: 96, child: const Text('Name')),
// placeholder: 'Enter your name',
// ),
CupertinoSelectFormFieldRow<Direction>(
title: Text('Direction'),
candidates: Direction.values,
initialValue: Direction.up,
),
CupertinoSelectFormFieldRow<PhoneType>(
title: Text('Phone Type'),
candidates: PhoneType.values,
initialValue: PhoneType.mobile,
),
],
),
),
);
}
}
class CupertinoSelectFormFieldRow<T> extends StatelessWidget {
final Widget title;
final List<T> candidates;
final T initialValue;
final String? Function(T)? validator;
final void Function(T)? onChanged;
final void Function(T)? onSaved;
const CupertinoSelectFormFieldRow({
super.key,
required this.title,
required this.candidates,
required this.initialValue,
this.validator,
this.onChanged,
this.onSaved,
});
Widget build(BuildContext context) {
return FormField<T>(
builder: (field) => CupertinoListTile(
title: title,
additionalInfo: Text(field.value!.toString()),
trailing: CupertinoListTileChevron(),
onTap: () async {
final selection = await showCupertinoModalPopup(
context: context,
builder: (context) => CupertinoActionSheet(
actions: candidates.map((candidate) {
return CupertinoActionSheetAction(
onPressed: () => Navigator.of(context).pop(candidate),
// We cannot use `candidate.title` here since `title` is not a
// valid property of type `T`. We could have let
// `T extends Enum` and use `candidate.name` but the `name`
// attribute of an enum value is not usually what we want.
child: Text(candidate.toString()),
);
}).toList(),
),
);
if (selection == null) return;
field.didChange(selection);
onChanged?.call(selection);
},
),
initialValue: initialValue,
validator: (selection) => validator?.call(selection as T),
onSaved: (selection) => onSaved?.call(selection as T),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment