卡片设置
一个用于构建基于卡片的设置表单的 Flutter 包。它包含一个预构建表单字段小部件库。风格有点像 Cupertino 设置屏幕和 Material Design 的混合体;其理念是它应该在 iOS 和 Android 上都可用且直观。

此包由 CardSettings 布局包装器和一系列表单字段选项组成,包括:
- 文本框
- CardSettingsText - 基本文本框
- CardSettingsParagraph - 带计数器的多行文本框
- CardSettingsEmail - 一个为电子邮件输入预配置的文本框
- CardSettingsPassword - 一个为密码预配置的文本框
- CardSettingsPhone - 一个带掩码的电话输入框(目前是美国风格)
- 数字字段
- CardSettingsDouble - 用于双精度数字的字段
- CardSettingsInt - 用于整数的字段
- CardSettingsCurrency - 用于货币输入的字段
- CardSettingsSwitch - 用于布尔状态的字段
- 选择器
- CardSettingsListPicker - 任意选项的选择列表
- CardSettingsNumberPicker - 指定范围内的数字选择列表
- CardSettingsColorPicker - RGB 颜色选择器
- CardSettingsDatePicker - Material Design 日期选择器
- CardSettingsTimePicker - Material Design 时间选择器
- 选择
- CardSettingsMultiselect - 从可用选项列表中选择
- 信息部分
- CardSettingsHeader - 用于在表单部分之间添加标题的控件
- CardSettingsInstructions - 信息性只读文本
- 操作
- CardSettingsButton - 表单的操作按钮
所有字段都支持 validate、onChange、onSaved、autovalidate 和 visible。
该包还包括以下附加项目:
- CardSettingsField - 基础布局小部件。您可以使用它来构建自定义字段
- Converters - 一组实用函数,用于协助数据在字段之间进行转换
简单示例
此包中的所有字段都兼容标准的 Flutter Form 小部件。只需将 CardSettings 控件包装在表单中,并像平常一样使用其表单功能即可。
String title = "Spheria";
String author = "Cody Leet";
String url = "http://www.codyleet.com/spheria"
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
body: Form(
key: _formKey,
child: CardSettings(
children: <Widget>[
CardSettingsHeader(label: 'Favorite Book'),
CardSettingsText(
label: 'Title',
initialValue: title,
validator: (value) {
if (value == null || value.isEmpty) return 'Title is required.';
},
onSaved: (value) => title = value,
),
CardSettingsText(
label: 'URL',
initialValue: url,
validator: (value) {
if (!value.startsWith('http:')) return 'Must be a valid website.';
},
onSaved: (value) => url = value,
),
],
),
),
);
}
在此处查看完整的演示示例:此处。
主题化
这些小部件支持 Material Design 主题。此示例显示了要设置哪些全局主题值来确定各种元素的显示方式。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Card Settings Example',
home: new HomePage(),
theme: ThemeData(
accentColor: Colors.indigo[400], // used for card headers
cardColor: Colors.white, // used for field backgrounds
backgroundColor: Colors.indigo[100], // color outside the card
primaryColor: Colors.teal, // color of page header
buttonColor: Colors.lightBlueAccent[100], // background color of buttons
textTheme: TextTheme(
button: TextStyle(color: Colors.deepPurple[900]), // style of button text
subhead: TextStyle(color: Colors.deepOrange[900]), // style of input text
),
),
);
}
}
或者,如果您想为 CardSettings 层级结构应用不同的主题,您可以像这样将其包装在 Theme 小部件中:
Theme(
data: Theme.of(context).copyWith(
primaryTextTheme: TextTheme(
title: TextStyle(color: Colors.lightBlue[50]), // style for headers
),
inputDecorationTheme: InputDecorationTheme(
labelStyle: TextStyle(color: Colors.deepPurple), // style for labels
),
),
child: CardSettings(
...
),
)
全局属性
CardSettings 小部件实现了几个全局设置,所有子字段都可以继承。目前它仅支持标签自定义。
标签
您可以通过四个属性来控制标签的渲染方式:
CardSettings(
labelAlign: TextAlign.right, // change the label alignment
labelSuffix: ':', // add an optional tag after the label
labelPadding: 10.0, // control the spacing between the label and the content
contentAlign: TextAlign.left, // alignment of the entry widgets
icon: Icon(Icons.person), // puts and option icon to the left of the label
requiredIndicator: Text('*', style: TextStyle(color: Colors.red)), // puts an optional indicator to the right of the label
)
labelAlign 和 contentAlign 属性也可在每个字段上使用,因此您可以为单个字段覆盖全局设置。
CardSettingsText(
label: 'Last Name',
labelAlign: TextAlign.left,
contentAlign: TextAlign.right,
)
动态可见性
每个字段都实现了一个 visible 属性,您可以使用它来根据其他字段的值控制可见性。在此示例中,开关字段控制文本框的可见性。
bool _ateOut = false;
CardSettingsSwitch(
label: 'Ate out?',
initialValue: _ateOut,
onChanged: (value) => setState(() => _ateOut = value),
),
CardSettingsText(
label: 'Restaurant',
visible: _ateOut,
),
掩码
CardSettingsText 小部件具有 inputMask 属性,可强制输入的文本符合给定模式。这是基于 flutter_masked_text
包构建的,因此掩码使用以下字符格式化:
- 0:接受数字
- A:接受字母
- @:接受数字和字母
- *:接受任何字符
例如,电话号码将是“(000)000-0000”。
注意:CardSettingsPhone 是一个便利小部件,已预先配置为使用此模式。
注意:flutter_masked_text 是一个控制器,因此您不能同时使用 inputMask 和自定义控制器。这可能在将来得到解决。
方向
此套件允许进行方向切换。要进行配置,请根据 MediaQuery 提供的方向构建不同的布局。
您可能希望在每个布局中使用不同的字段,或者不同的字段顺序。为了避免 Flutter 在此情况下跟踪状态时感到困惑,您必须为每个单独的字段提供一个唯一的 state key,并在每个布局中使用相同的 key。
@override
Widget build(BuildContext context) {
final GlobalKey<FormState> _emailKey = GlobalKey<FormState>();
var orientation = MediaQuery.of(context).orientation;
return Form
key: _formKey,(
child: (orientation == Orientation.portraitUp)
? CardSettings(children: <Widget>[
// Portrait layout here
CardSettingsEmail(key: _emailKey)
])
: CardSettings(children: <Widget>[
// Landscape layout here
CardSettingsEmail(key: _emailKey)
]);
},
);
}
在横向模式下,您可以在同一行上放置多个字段。这通常需要使用容器小部件在行内提供布局。相反,您可以使用 CardFieldLayout 辅助小部件来简化此操作。它默认会使子项均匀分布,但您可以提供一个 flex 值数组来控制相对大小。
// equally spaced example
CardSettings(
children: <Widget>[
CardFieldLayout(children: <Widget>[
CardSettingsEmail(),
CardSettingsPassword(),
]),
],
);
// relative width example
CardSettings(
children: <Widget>[
CardFieldLayout_FractionallySpaced(
children: <Widget>[
CardSettingsEmail(),
CardSettingsPassword(),
],
flexValues: [2, 1], // 66% and 33% widths
),
],
);
自定义字段
CardSettingsField 是所有其他字段的基础,可用于构建此库之外的唯一字段。它的目的是以一致的装饰来管理布局。制作自定义字段的最佳方法是继承自 FormField<T>,它将管理您的字段状态。CardSettingsSwitch 小部件是这方面最清晰的例子。您只需要在 content 属性中提供自定义小部件。