17.表单
class FormTestRoute extends StatefulWidget {
@override
_FormTestRouteState createState() => new _FormTestRouteState();
}
class _FormTestRouteState extends State<FormTestRoute> {
//文本框的控制器,通过它可以设置/获取编辑框的内容、选择编辑内容、监听编辑文本改变事件
TextEditingController _unameController = new TextEditingController();
TextEditingController _pwdController = new TextEditingController();
//用来获取FormState
GlobalKey _formKey= new GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title:Text("Form Test"),
),
body: Padding(
//设置水平和垂直方向的间距(空白部分)
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
//表单组件
child: Form(
key: _formKey, //设置globalKey,用于后面获取FormState
autovalidate: true, //开启自动校验
child: Column(
children: <Widget>[
//表单中的文本框
TextFormField(
//自动聚焦
autofocus: true,
//设置控制器
controller: _unameController,
decoration: InputDecoration(
//设置标签文本
labelText: "用户名",
//设置提示文本
hintText: "用户名或邮箱",
//设置图标
icon: Icon(Icons.person)
),
// 校验用户名
validator: (v) {
return v
.trim()
.length > 0 ? null : "用户名不能为空";
}
),
TextFormField(
controller: _pwdController,
decoration: InputDecoration(
labelText: "密码",
hintText: "您的登录密码",
icon: Icon(Icons.lock)
),
//隐藏文本
obscureText: true,
//校验密码
validator: (v) {
return v
.trim()
.length > 5 ? null : "密码不能少于6位";
}
),
// 登录按钮
Padding(
padding: const EdgeInsets.only(top: 28.0),
child: Row(
children: <Widget>[
Expanded(
child: RaisedButton(
padding: EdgeInsets.all(15.0),
child: Text("登录"),
color: Colors.red,
textColor: Colors.white,
onPressed: () {
// 通过_formKey.currentState 获取FormState后,
// 调用validate()方法校验用户名密码是否合法,校验
// 通过后再提交数据。
if((_formKey.currentState as FormState).validate()){
//验证通过提交数据
}
},
),
),
],
),
)
],
),
),
),
);
}
}
效果:
18.线性进度条
// 线性进度条高度指定为3
SizedBox(
height: 3,
child: LinearProgressIndicator(
backgroundColor: Colors.grey[200],
valueColor: AlwaysStoppedAnimation(Colors.blue),
value: .5,
),
),
效果:
19.线性布局
Column(
//测试Row对齐方式,排除Column默认居中对齐的干扰
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
//Row组件内居中对齐
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(" hello world "),
Text(" I am Jack "),
],
),
Row(
mainAxisSize: MainAxisSize.min,
//如果mainAxisSize值为MainAxisSize.min,则此属性无意义
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(" hello world "),
Text(" I am Jack "),
],
),
Row(
//Row组件内左对齐
mainAxisAlignment: MainAxisAlignment.end,
//Text文本由右到左显示
textDirection: TextDirection.rtl,
children: <Widget>[
Text(" hello world "),
Text(" I am Jack "),
],
),
Row(
//Row组件内底对齐
crossAxisAlignment: CrossAxisAlignment.start,
//从低向顶排列
verticalDirection: VerticalDirection.up,
children: <Widget>[
Text(" hello world ", style: TextStyle(fontSize: 30.0),),
Text(" I am Jack "),
],
),
],
),
效果:
20.弹性布局
class FlexLayoutTestRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
//Flex的两个子widget按1:2来占据水平空间
Flex(
//占据水平空间
direction: Axis.horizontal,
children: <Widget>[
//占比为1的空间块
Expanded(
flex: 1,
child: Container(
//这里面的height是正常的
height: 30.0,
color: Colors.red,
),
),
//占比为2的空间块
Expanded(
flex: 2,
child: Container(
height: 30.0,
color: Colors.green,
),
),
],
),
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: SizedBox(
//设置总高度为100
height: 100.0,
//Flex的三个子widget,在垂直方向按2:1:1来占用100像素的空间
child: Flex(
//占据垂直空间
direction: Axis.vertical,
children: <Widget>[
//占据总高度的1/2
Expanded(
flex: 2,
child: Container(
//这里面的height是不起作用的,以占比为主
height: 15.0,
color: Colors.red,
),
),
//占据总高度的1/4
Spacer(
flex: 1,
),
//占据总高度的1/4
Expanded(
flex: 1,
child: Container(
//这里面的height是不起作用的,以占比为主
height: 30.0,
color: Colors.green,
),
),
],
),
),
),
],
);
}
}
效果: