
前言
很高兴遇见你~
在本系列的上一篇文章中,我们介绍了 Flutter 中常用的按钮 Widget,Flutter 1.x 和 Flutter 2.x 按钮的变化,最后通过 Flutter 1.x 相关 Button + BottomNavigationBar + FloatingActionButton 实现了一个综合案例。还没有看过上一篇文章的朋友,建议先去阅读 Flutter 系列(五):Flutter 常用按钮 Widget。接下来我们对 Flutter 表单 Widget 进行学习
Flutter 中常见的表单有:TextField,CheckBox,Radio,Switch,CheckboxListTile,RadioListTile,SwitchListTile,Slider 等,下面就介绍一下这些常用的 Widget
1.1、TextFiled 文本框
TextFiled 是 Flutter 给我们提供的文本框 Widget,其常用的属性有:
属性名称 |
属性类型 |
说明 |
maxLines |
int |
设置此参数可以把文本框改为多行文本框 |
onChanged |
ValueChanged |
文本框改变时触发的事件 |
decoratioin |
InputDecoration |
装饰,InputDecoration 常用属性: hintText:默认提示文案 border:文本框边框,配合 OutlineInputBorder 使用 labelText:label 的名称 labelStyle:配置 label 的样式 |
obscureText |
bool |
是否把文本框改为密码框 |
controller |
TextEditingController |
配置文本框默认显示的内容 |
运行下面代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| import 'package:flutter/material.dart';
void main() { runApp(MaterialApp( home: Scaffold( appBar: AppBar( title: Text("Flutter Form Practice"), ), body: MyBodyPage(), ) )); }
class MyBodyPage extends StatelessWidget{
@override Widget build(BuildContext context) { return Padding( padding: EdgeInsets.all(20), child: Column( children: [ TextField( maxLines: 1, decoration: InputDecoration( hintText: "please input account", label: Text("Account") ), ), SizedBox(height: 20), TextField( maxLines: 1, obscureText: true, decoration: InputDecoration( hintText: "please input password", label: Text("Password") ), ) ], ), ); } }
|
效果:
1.2、Checkbox,CheckboxListTile 复选框
Checkbox 是 Flutter 给我们提供的复选框 Widget,常用属性有:
属性名称 |
属性类型 |
说明 |
value |
bool |
必填项,true:选中,false:未选中 |
onChanged |
ValueChanged |
必填项,改变时触发的事件 |
activeColor |
Color |
选中的背景颜色 |
checkColor |
Color |
选中复选框里面符号的颜色 |
CheckboxListTile 是 Flutter 给我们提供的复选框列表 Item,常用属性有:
属性名称 |
属性类型 |
说明 |
value |
bool |
必填项,true:选中,false:未选中 |
onChanged |
ValueChanged |
必填项,改变时触发的事件 |
activeColor |
Color |
选中的背景颜色,如果 selected 为 true ,则 title,subtitle,secondary 也会变 |
checkColor |
Color |
选中复选框里面符号的颜色 |
title |
Widget |
标题 |
subtitle |
Widget |
二级标题 |
secondary |
Widget |
配置显示的图标或图片 |
selected |
bool |
选中时其它子 Widget 颜色是否跟着改变 |
在这之前,我们自定义 Wdiget 都是继承 StatelessWidget,但表单相关的 Widget 都是有状态的,因此需要继承 StatefulWidget 来动态展示它的一个状态,继承 StatefulWidget 的一个标准模版如下:
1 2 3 4 5 6 7 8 9 10 11 12
| class MyBodyPage extends StatefulWidget{ @override State<StatefulWidget> createState() => _MyBodyPageState(); }
class _MyBodyPageState extends State<MyBodyPage>{ @override Widget build(BuildContext context) { throw UnimplementedError(); } }
|
接下来我们使用 Checkbox,CheckboxListTile 来实践一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| import 'package:flutter/material.dart';
void main() { runApp(MaterialApp( home: Scaffold( appBar: AppBar( title: Text("Flutter Form Practice"), ), body: MyBodyPage(), ) )); }
class MyBodyPage extends StatefulWidget{ @override State<StatefulWidget> createState() => _MyBodyPageState(); }
class _MyBodyPageState extends State<MyBodyPage> {
var flag1 = false; var flag2 = false; var flag3 = false;
@override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Checkbox( value: flag1, onChanged: (value){ setState(() { flag1 = value??false; }); }, ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(flag1 == true ? "选中" : "未选中") ], ), Divider(color: Colors.black), CheckboxListTile(value: flag2, onChanged: (value){ setState(() { flag2 = value??false; }); }, activeColor: Colors.green, checkColor: Colors.black, title: Text('标题'), subtitle: Text("描述"), selected: flag2, ),
Divider(color: Colors.black),
CheckboxListTile(value: flag3, onChanged: (value){ setState(() { flag3 = value??false; }); }, title: Text('标题'), subtitle: Text("描述"), secondary: Icon(Icons.home), selected: false, ) ], ); } }
|
效果:
1.3、Radio,RadioListTile 单选框
Radio,RadioListTile 是 Flutter 给我们提供的单选框和单选框列表 Item,它的常用属性和 Checkbox,CheckboxListTile 非常类似,区别就是:Radio,RadioListTile 必须提供一个 groupValue 属性用于记录单选框的分组,直接上代码感受下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| import 'package:flutter/material.dart';
void main() { runApp(MaterialApp( home: Scaffold( appBar: AppBar( title: Text("Flutter Form Practice"), ), body: MyBodyPage(), ) )); }
class MyBodyPage extends StatefulWidget { @override State<StatefulWidget> createState() => _MyBodyPageState(); }
class _MyBodyPageState extends State<MyBodyPage> { int sex = 1; bool flag = true;
@override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text("男"), Radio( value: 1, onChanged: (value) { setState(() { sex = value as int; }); }, groupValue: sex), SizedBox(width: 20), Text("女"), Radio( value: 2, onChanged: (value) { setState(() { sex = value as int; }); }, groupValue: sex) ], ), SizedBox(height: 20), Divider(), RadioListTile( value: true, onChanged: (value) { setState(() { flag = value as bool; }); }, groupValue: flag, title: Text("一级标题"), subtitle: Text("二级标题"), secondary: Icon(Icons.home), ), RadioListTile( value: false, onChanged: (value) { setState(() { flag = value as bool; }); }, groupValue: flag, title: Text("一级标题"), subtitle: Text("二级标题"), secondary: Image.network( "https://img.lianzhixiu.com/uploads/210106/37-21010609363aS.jpg"), ) ], ); } }
|
效果:
1.4、Switch,SwitchListTile 开关
Switch,SwitchListTile 是 Flutter 给我们提供的开关和开关列表 Item,常用属性和上面两个类似,我们快速过一下:
代码实践:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| import 'package:flutter/material.dart';
void main() { runApp(MaterialApp( home: Scaffold( appBar: AppBar( title: Text("Flutter Form Practice"), ), body: MyBodyPage(), ) )); }
class MyBodyPage extends StatefulWidget { @override State<StatefulWidget> createState() => _MyBodyPageState(); }
class _MyBodyPageState extends State<MyBodyPage> { bool flag = true;
@override Widget build(BuildContext context) { return Column( children: [ Switch( value: flag, onChanged: (value) { setState(() { flag = value; }); }), SizedBox(height: 20), SwitchListTile( value: flag, onChanged: (value) { setState(() { flag = value; }); }, title: Text("标题"), subtitle: Text("副标题"), secondary: Image.network( "https://img.lianzhixiu.com/uploads/210106/37-21010609363aS.jpg" ) ) ], ); } }
|
效果:
1.5、Slider 进度条
Slider 是 Flutter 给我们提供的进度条 Widget。其常用属性有:
属性名称 |
属性类型 |
说明 |
value |
double |
必填项,当前 Slider 滑块位置的值,注意不可以超出 min 和 max 的范围,否则会报错 |
onChanged |
ValueChanged |
必填项,正在滑动或者点击,未松手 |
onChangeStart |
ValueChanged |
刚开始点击 |
onChangeEnd |
ValueChanged |
滑动或者点击结束,已松手 |
min |
double |
最小值,默认为 0.0 |
max |
double |
最大值,默认为 1.0 |
activeColor |
Color |
滑块颜色 |
inactiveColor |
Color |
轨道颜色 |
label |
String |
气泡文本 |
divisions |
int |
刻度,如没有刻度,label 则不会展示 |
代码实践:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| import 'package:flutter/material.dart';
void main() { runApp(MaterialApp( home: Scaffold( appBar: AppBar( title: Text("Flutter Form Practice"), ), body: MyBodyPage(), ) )); }
class MyBodyPage extends StatefulWidget{
@override State<StatefulWidget> createState() => _MyBodyPageState(); }
class _MyBodyPageState extends State<MyBodyPage>{ double sliderValue = 0;
void updateSlider(value){ sliderValue = value; setState(() {
}); }
@override Widget build(BuildContext context) { return Padding( padding: EdgeInsets.all(20), child: Column( children: [ _slider() ], ), ); }
Slider _slider(){ return Slider( value: sliderValue, max: 100, activeColor: Colors.red, inactiveColor: Colors.green, label: "进度:$sliderValue", divisions: 10, onChanged: (value){ updateSlider(value); }, onChangeStart: (value){ updateSlider(value); }, onChangeEnd: (value){ updateSlider(value); }, ); } }
|
效果:
我们还可以使用 SliderTheme 嵌套 Slider 实现各种自定义样式,这里就不做演示了,SliderTheme 常用属性有:
属性名称 |
属性类型 |
说明 |
data |
SliderThemeData |
必填项,通过 SliderThemeData 实现各种自定义样式 |
child |
Widget |
必填项,子 Widget |
SliderThemeData 属性介绍:https://api.flutter.dev/flutter/material/SliderThemeData-class.html
接下来,我们就使用表单 Widget 做一个用户信息登记系统,效果如下:
按照惯例,我们先分析这个页面:
1、可以看到这是一个从上往下的垂直布局,有个内边距,子 Widget 是自适应的,这里我们可以使用 ListView 并设置一个 padding 实现
2、然后从上往下依次是,输入姓名:文本框(TextField),性别选择:单选框(Radio),兴趣爱好:复选框(Checkbox),颜值打分:滑块(Slider),永不宕机:开关(SwitchListTile),获取用户信息(RaisedButton),用户信息展示(Text)
3、这些 Widget 都是有状态的,因此我们需要继承 StatefulWidget,并使用 setState 方法去更新状态
我们画一张图来理一下 Widget 之间的树形结构:
最后我们进行代码实现,里面写了详细的注释:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
| import 'package:flutter/material.dart';
void main() { runApp(MaterialApp( home: Scaffold( appBar: AppBar( title: Text("用户信息登记系统"), ), body: MyBodyPage(), ) )); }
class MyBodyPage extends StatefulWidget { @override State<StatefulWidget> createState() => _MyBodyPageState(); }
class _MyBodyPageState extends State<MyBodyPage> {
String userName = ""; int sex = 1; bool flag = false; double sliderValue = 0; List hobbies = [ {"checked": false, "title": "打篮球"}, {"checked": false, "title": "爬山"}, {"checked": false, "title": "写代码"}, ]; String info = "";
@override Widget build(BuildContext context) { return ListView( padding: EdgeInsets.all(20), children: [ TextField( decoration: InputDecoration( hintText: "请输入用户姓名", label: Text("姓名") ), onChanged: (str){ setState(() { userName = str; }); }, ), SizedBox(height: 10), Text("性别:"), Row( children: [ Text("男"), Radio(value: 1, groupValue: sex, onChanged: _sexChanged), Text("女"), Radio(value: 2, groupValue: sex, onChanged:_sexChanged) ], ), Text("兴趣爱好:"), Row( children: _getHobbies(), ), _slider(), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text("颜值:$sliderValue分"), ], ), SwitchListTile( value: flag, title: Text("永不宕机"), onChanged: (value){ setState(() { flag = value; }); } ), RaisedButton( child: Text("获取用户信息"), onPressed: (){ setState(() { info = getInfo(); }); }, color: Colors.blue, textColor: Colors.white, ),
Text(info) ], ); }
String getInfo() { String hobbiesStr = ""; for (var element in hobbies) { if(element["checked"]){ hobbiesStr += element["title"] + ","; } } return "$userName,性别${sex == 1 ? "男" : "女"},喜欢$hobbiesStr${flag ? "永不宕机," : ""}颜值$sliderValue分"; }
void _sexChanged(value){ setState(() { sex = value as int; }); }
void updateSlider(value){ sliderValue = value; setState(() {
}); }
List<Widget> _getHobbies() { List<Widget> temp = []; for (var element in hobbies) { temp.add(Text(element["title"])); temp.add(Checkbox( value: element["checked"], onChanged: (value) { setState(() { element["checked"] = value; }); })); } return temp; }
Slider _slider(){ return Slider( value: sliderValue, max: 100, label: "颜值:$sliderValue分", divisions: 10, onChanged: (value){ updateSlider(value); }, onChangeStart: (value){ updateSlider(value); }, onChangeEnd: (value){ updateSlider(value); }, ); } }
|
三、总结
本篇文章我们介绍了:
1、Flutter 中常用的表单 Widget :TextField,CheckBox,Radio,Switch,CheckboxListTile,RadioListTile,SwitchListTile,Slider 的常用属性和使用,以及它们的显示效果
2、通过表单 Widget 组合实现了一个用户信息登记系统
好了,本篇文章到这里就结束了,希望能给你带来帮助 🤝
感谢你阅读这篇文章
下篇预告
后续不会花大篇幅去介绍 Widget,我会穿插在其它知识点中简单介绍下,Flutter 中有 400 多个 Widget,不可能每个都去学,我的建议:掌握常用的,其它用到时在去官网查询。
下篇文章我会讲 Flutter 中的路由以及实际开发中请求 Http 接口渲染页面,尽请期待吧🍺
参考和推荐
Flutter 教程:通俗易懂的 Flutter 入门教程
你的点赞,评论,是对我巨大的鼓励!
欢迎关注我的公众号: sweetying ,文章更新可第一时间收到
如果有问题,公众号内有加我微信的入口,在技术学习、个人成长的道路上,我们一起前进!