表单,页面中负责数据采集功能的控件。
在原生Android中EditText输入框,是重要的数据采集控件。而Flutter中TextField就是与EditText对应的重要的输入框控件,并且TextField属性和效果要比EditText强大不少。比如自带边框,输入动画等。
常用属性(具体的参考官方文档或查看源码):
child: new TextField(
autocorrect: false, // 是否自动校正
autofocus: false, //自动获取焦点
enabled: true, // 是否启用
inputFormatters: [], //对输入的文字进行限制和校验
keyboardType: TextInputType.text, //获取焦点时,启用的键盘类型
maxLines: 2, // 输入框最大的显示行数
maxLength: 3, //允许输入的字符长度/
maxLengthEnforced: false, //是否允许输入的字符长度超过限定的字符长度
obscureText: true, // 是否隐藏输入的内容
onChanged: (newValue) {
// print(newValue); // 当输入内容变更时,如何处理
},
onSubmitted: (value) {
// print("whar"); // 当用户确定已经完成编辑时触发
},
style: new TextStyle(
color: new Color(Colors.amberAccent.green)), // 设置字体样式
textAlign: TextAlign.center, //输入的内容在水平方向如何显示
decoration: new InputDecoration(
labelText: "姓名",
icon: new Icon(Icons.location_city),
border: new OutlineInputBorder(), // 边框样式
helperText: 'helper required',//帮助提示信息
hintText: '输入姓名',//提示语句
prefixIcon: new Icon(Icons.games),//输入框最前面图标, prefix —— 前缀
prefixText: 'Hello'),//输入框prefixIcon后面文字
),
以下为演示代码:
在main.dart中配置主题 和 根路由页面 FormPage.dart:
import 'package:flutter/material.dart';
import 'FormPage.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
initialRoute: '/', //使用带名称的路由,指定跟路由
routes: {
'/': (context) => FormPage(), // '/'路由 对应页面FormPage
},
theme: ThemeData(primaryColor: Colors.deepPurple),
);
}
}
根路由页面(FormPage.dart)中显示垂直布局Column,在其中放置两个TextField (在demo文件夹有 TextFieldDemo.dart 和 TextFieldDemo2.dart)。
import 'package:flutter/material.dart';
import 'demo/TextFieldDemo.dart';
import 'demo/TextFieldDemo2.dart';
class FormPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('FormPage'),
centerTitle: true, //title内容居中
),
body: Theme(
//重新定义主题
data: ThemeData(
primaryColor: Colors.white70,
),
child: FromPageTest(),
),
);
}
}
class FromPageTest extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color:Theme.of(context).primaryColor, //设置颜色跟随主题颜色(跟随最近设置的)
padding: EdgeInsets.all(12.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
TextFieldDemo(),
SizedBox(height: 10,),
TextFieldDemo2(),
],
),
);
}
}
其中,TextFieldDemo.dart页面演示TextField的常用属性:
import 'package:flutter/material.dart';
class TextFieldDemo extends StatefulWidget {
@override
_TextFieldDemoState createState() => _TextFieldDemoState();
}
class _TextFieldDemoState extends State<TextFieldDemo> {
@override
Widget build(BuildContext context) {
return TextField(
//设置TextField 样式属性
decoration: InputDecoration(
icon: Icon(
Icons.person,
size: 28.0,
color: Colors.deepPurple,
), //文本框左侧图标
labelText: 'Name', //文本框标题
hintText: '输入姓名', //提示语句
// border: InputBorder.none, //文本框没有边框
//文本框有全边框,borderRadius设置边框倒角
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
),
// filled: true, //显示文本框背景颜色
// fillColor: Colors.orange, //文本框背景颜色
helperText: '以上需要您输入Name', //帮助提示信息
helperStyle: TextStyle(fontSize: 12, color: Colors.red), //帮助提示信息Style
suffixText: '@@' //后缀 邮箱 或者 金额需要这些
),
// 监听每次输入字符
onChanged: (value) {
debugPrint('每次输入字符------:$value');
},
// 监听按下键盘确定按钮
onSubmitted: (value) {
debugPrint('按下确定按钮------:$value');
},
//
onEditingComplete: () {
debugPrint('--EditingComplete');
},
//修改键盘属性
// keyboardType: TextInputType.number,
// textInputAction: TextInputAction.continueAction,
// textCapitalization: TextCapitalization.sentences,
);
}
}
在 TextFieldDemo2.dart 中使用另一种监听值输入的方式(TextEditingController),这个方式可以设定初始值:
import 'package:flutter/material.dart';
class TextFieldDemo2 extends StatefulWidget {
@override
_TextFieldDemo2State createState() => _TextFieldDemo2State();
}
class _TextFieldDemo2State extends State<TextFieldDemo2> {
//TextEditingController步骤1
final editingController = TextEditingController();
//TextEditingController步骤3 设置初始值,增加监听器
@override
void initState() {
super.initState();
editingController.text = '初始Name';
editingController.addListener(() {
debugPrint('Changed:${editingController.text}');
});
}
//TextEditingController步骤4 使用完 TextEditingController 需要注销 dispose
@override
void dispose() {
editingController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return TextField(
decoration: InputDecoration(
icon: Icon(Icons.person_add), border: OutlineInputBorder()),
//TextEditingController步骤2 监听输入 可设置初始值
controller: editingController,
);
}
}
演示效果:
上边的是TextFieldDemo.dart,下边的是TextFieldDemo2.dart。
Flutter中的Form组件和html中的的作用类似,都是起到了一个容器的作用。里面可以包含多个TextFormField,便于多个输入框的统一管理和操作。
以下以用户注册为场景进行演示:
1、main.dart与前文中代码一样,只是作为根路由的引入;
2、FormPage.dart与前文基本一样,只是加入了RegisterForm.dart,而注释了其他展示控件;
import 'package:flutter/material.dart';
import 'demo/TextFieldDemo.dart';
import 'demo/TextFieldDemo2.dart';
import 'demo/RegisterForm.dart';
class FormPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('FormPage'),
centerTitle: true, //title内容居中
),
body: Theme(
//重新定义主题
data: ThemeData(
primaryColor: Colors.white70,
),
child: FromPageTest(),
),
);
}
}
class FromPageTest extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color:Theme.of(context).primaryColor, //设置颜色跟随主题颜色(跟随最近设置的)
padding: EdgeInsets.all(12.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
// TextFieldDemo(),
// SizedBox(height: 10,),
// TextFieldDemo2(),
// SizedBox(height: 20,),
RegisterFrom(),//注册页面
],
),
);
}
}
3、RegisterFrom.dart注册页面代码逻辑。
其中展示了:
①、Form 与 TextFormField纵向布局的用法;
②、obscureText使输入内容变为小黑点展示;
③、validator 进行输入内容验证;
④、autovalidate 进行自动验证,并扩展为 初始默认不自动验证,当提交验证不通过时,才开启自动验证功能。
import 'package:flutter/material.dart';
class RegisterFrom extends StatefulWidget {
@override
_RegisterFromState createState() => _RegisterFromState();
}
class _RegisterFromState extends State<RegisterFrom> {
//声明GlobalKey 便于下面进行保存信息的操作
final registerKey = GlobalKey<FormState>();
String username, password; //定义需要保存的值的变量
bool autovalidate = false; //默认不进行自动验证
@override
Widget build(BuildContext context) {
return Form(
key: registerKey,
child: Column(
children: <Widget>[
TextFormField(
decoration: InputDecoration(labelText: '用户:', helperText: ''),
onSaved: (value) {
username = value; //将输入的值,赋值给username
},
validator: validatorUsername, //添加验证
autovalidate: autovalidate, //validator是否进行自动验证
),
TextFormField(
obscureText: true, //输入内容显示成小圆点
decoration: InputDecoration(labelText: '密码:', helperText: ''),
onSaved: (value) {
password = value; //将输入的值,赋值给password
},
validator: validatorPassword, //添加验证
autovalidate: autovalidate,
),
//使注册按钮和 输入框直接有一定间距
SizedBox(
height: 20.0,
),
Container(
width: double.infinity,
child: RaisedButton(
color: Theme.of(context).accentColor, //以主题颜色
child: Text(
'注册',
style: TextStyle(color: Colors.white),
),
elevation: 0.0,
onPressed: submitFrom, //不设置onPressed 按钮为灰色,不显示设定颜色
),
),
],
),
);
}
//点击注册按钮,进行的逻辑动作
//默认不进行自动验证,autovalidate = false,点击注册时,才会打开自动验证功能。
void submitFrom() {
// registerKey.currentState.validate(); 进行当前信息验证,这里会返回bool值
if (registerKey.currentState.validate()) {
registerKey.currentState.save(); //保存当前输入信息
//底部弹出 SnackBar
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('正在注册.... 用户:$username ,密码:$password'),
));
} else {
setState(() {
autovalidate = true; //有空值,开启自动验证
});
}
}
//验证Password
String validatorPassword(value) {
if (value.isEmpty) {
return '密码不为空!';
}
return null;
}
//验证Username
String validatorUsername(value) {
if (value.isEmpty) {
return '用户名不为空!';
}
return null;
}
}