Last active
March 10, 2024 14:54
-
-
Save luangong/035eac0d9b387b47199ab012cde30d91 to your computer and use it in GitHub Desktop.
CupertinoSelectFormFieldRow
This file contains 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
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