上一节说到TextField,今天详细研究下这个控件。
import 'package:flutter/material.dart';
class LoginView extends StatefulWidget {
const LoginView({super.key});
@override
State<LoginView> createState() {
return LoginViewState();
}
}
class LoginViewState extends State<LoginView> {
TextEditingController phoneController = TextEditingController();
TextEditingController pwdController = TextEditingController();
void login() {
print({'phone': phoneController.text, 'pwd': pwdController.text});
if (phoneController.text.length != 11) {
showDialog(
context: context,
builder: (context) => const AlertDialog(
title: Text('手机号长度不对'),
));
} else if (pwdController.text.isEmpty) {
showDialog(
context: context,
builder: (context) => const AlertDialog(
title: Text('密码不能为空'),
));
} else {
showDialog(
context: context,
builder: (context) => const AlertDialog(
title: Text('login success'),
));
phoneController.clear();
pwdController.clear();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("please login"),
),
body: Column(
children: <Widget>[
const Text(
'登录演示',
style: TextStyle(
color: Color(0xffff9900),
decoration: TextDecoration.underline,
decorationColor: Color(0xffff9900),
fontSize: 21),
),
TextField(
controller: phoneController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
contentPadding: EdgeInsets.all(10),
icon: Icon(Icons.phone),
labelText: "please enter username",
helperText: "Please enter 11 numbers"),
autofocus: false,
),
TextField(
controller: pwdController,
decoration: const InputDecoration(
contentPadding: EdgeInsets.all(10),
icon: Icon(Icons.lock),
labelText: "please enter password",
helperText: "Please enter password"),
obscureText: true,
),
TextButton(onPressed: login, child: const Text("Login")),
],
),
);
}
}
简单介绍下,使用TextField的时候,需要在State里去声明TextEditingController phoneController = TextEditingController();
并在控件TextField实例化的时候在controller处绑定,这样就可以用phoneController.text以及phoneController.clear()来操作控件内容了。
TextField 有基本属性,常用的有
this.controller,//控制器
this.focusNode,//焦点
this.obscureText = false,//是否隐藏文本,即显示密码类型
this.maxLines = 1,//最多行数,高度与行数同步
this.autofocus = false,//自动聚焦
this.decoration = const InputDecoration(),//装饰
TextInputType keyboardType,//键盘类型,即输入类型
this.onChanged,//输入改变回调
this.textInputAction,//键盘按钮
this.textCapitalization = TextCapitalization.none,//大小写
其中有一个InputDecoration类型的decoration(装饰器),主要控制外观以及提示信息等。
InputDecoration({
this.icon, //位于装饰器外部和输入框前面的图片
this.labelText, //用于描述输入框,例如这个输入框是用来输入用户名还是密码的,当输入框获取焦点时默认会浮动到上方,
this.labelStyle, // 控制labelText的样式,接收一个TextStyle类型的值
this.helperText, //辅助文本,位于输入框下方,如果errorText不为空的话,则helperText不会显示
this.helperStyle, //helperText的样式
this.hintText, //提示文本,位于输入框内部
this.hintStyle, //hintText的样式
this.hintMaxLines, //提示信息最大行数
this.errorText, //错误信息提示
this.errorStyle, //errorText的样式
this.errorMaxLines, //errorText最大行数
this.hasFloatingPlaceholder = true, //labelText是否浮动,默认为true,修改为false则labelText在输入框获取焦点时不会浮动且不显示
this.isDense, //改变输入框是否为密集型,默认为false,修改为true时,图标及间距会变小
this.contentPadding, //内间距
this.prefixIcon, //位于输入框内部起始位置的图标。
this.prefix, //预先填充的Widget,跟prefixText同时只能出现一个
this.prefixText, //预填充的文本,例如手机号前面预先加上区号等
this.prefixStyle, //prefixText的样式
this.suffixIcon, //位于输入框后面的图片,例如一般输入框后面会有个眼睛,控制输入内容是否明文
this.suffix, //位于输入框尾部的控件,同样的不能和suffixText同时使用
this.suffixText,//位于尾部的填充文字
this.suffixStyle, //suffixText的样式
this.counter,//位于输入框右下方的小控件,不能和counterText同时使用
this.counterText,//位于右下方显示的文本,常用于显示输入的字符数量
this.counterStyle, //counterText的样式
this.filled, //如果为true,则输入使用fillColor指定的颜色填充
this.fillColor, //相当于输入框的背景颜色
this.errorBorder, //errorText不为空,输入框没有焦点时要显示的边框
this.focusedBorder, //输入框有焦点时的边框,如果errorText不为空的话,该属性无效
this.focusedErrorBorder, //errorText不为空时,输入框有焦点时的边框
this.disabledBorder, //输入框禁用时显示的边框,如果errorText不为空的话,该属性无效
this.enabledBorder, //输入框可用时显示的边框,如果errorText不为空的话,该属性无效
this.border, //正常情况下的border
this.enabled = true, //输入框是否可用
this.semanticCounterText,
this.alignLabelWithHint,
})
这些属性用到的时候再看就可以。
做项目的时候 经常会有焦点问题,比如让textField失去焦点,让textField成为第一响应者等等,那么我们需要在State里去声明一个 FocusNode useFocusNode = FocusNode();
然后在textField实例化的时候定义focuseNode参数为 useFocusNode。这样在逻辑地方可以调用useFocusNode.requestFocus();
来获取焦点,useFocusNode.unfocus();
来失去焦点。
有时候键盘弹出的时候会把我们某些控件挡住,iOS是设置contentInset,flutter解决办法有两种, 第一种是用ScrollView或者ListView等可以滚动的空间包裹,可以用过padding来实现键盘不被遮挡的问题。
//没有亲自试过
Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom
),
child: TextField(
)
)
第二种是通过Scaffold,它是自带自适应的输入法弹出的,有个属性是resizeToAvoidBottomInset,默认true适应键盘模式。
参考链接:https://blog.csdn.net/jia635/article/details/118307091
https://www.jianshu.com/p/8bac3d2a4e63/