设计给的效果如下:
UI布局图拿到设计后,先把整体拆分成几个部分:
- “文本输入框”,使用文本字段(
TextField
)组件实现的输入框。 - “状态指示条”,使用容器(
Container
)组件实现带颜色的长方形。
然后就可以开始进行编码了。
第1步:绘制组件树
带彩条的文本字段的组件树.png第2步:实现“文本输入框”
Flutter的布局代码嵌套非常深,为了代码的可读性,你可以先把一部分没有依赖的纯样式代码提取出来。
import 'package:flutter/material.dart';
// 文字样式(`TextStyle`)组件,一个不透明的对象,用于确定文本的大小,位置和呈现。
/// 文本域(`TextField`)组件使用的样式。
final TextStyle _textFieldStyle = TextStyle(
// 字体大小。
fontSize: 22.0,
// 字母间距。
letterSpacing: 0.78,
// 字体系列。
fontFamily: 'BebasNeueBold',
// 颜色。
color: const Color(0xFF4A4A4A),
);
/// 输入装饰(`InputDecoration`)组件的提示样式(`hintStyle`)属性值。
final TextStyle _hintStyle = TextStyle(
fontSize: 16.0,
color: const Color(0xFF9B9B9B),
);
定义一下该自定义组件构建时需要的成员变量,并在默认构建函数中传递一下调用者提供的参数。
/// 自定义的登录表单字段组件。
class LoginFormField extends StatefulWidget {
/// 字段内的提示文字。
final String hintText;
/// 文本字段的控制器。
final TextEditingController textEditingController;
/// 文本字段的最大长度。
final int maxLength;
/// 文本字段的最小长度。
final int minLength;
/// 文本字段长度合理时的回调函数。
final Function legitimateCallback;
/// 文本字段长度不合理时的回调函数。
final Function illegalCallback;
LoginFormField({
@required
this.hintText,
this.textEditingController,
this.maxLength,
this.minLength,
this.legitimateCallback,
this.illegalCallback,
});
@override
_LoginFormFieldState createState() => _LoginFormFieldState();
}
先写好一个垂直(Column
)组件,接下来会在垂直(Column
)组件中具体实现“文本输入框”和“状态指示条”。
/// 与自定义的登录表单字段组件关联的状态子类。
class _LoginFormFieldState extends State<LoginFormField> {
/// 文本字段下方的提示颜色。
Color inputColor;
@override
void initState() {
super.initState();
inputColor = Color(0xFFC5C5C5);
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
// TODO: 实现“文本输入框”。
// TODO: 第3步:实现“状态指示条”。
],
);
}
}
通过设置文本字段(TextField
)组件的属性和方法,实现UI图的效果。同时通过简单的文本长度来校验数据是否合法,当前你可以添加更多的校验逻辑,来满足业务需求。
// TODO: 实现“文本输入框”。
// 文本字段(`TextField`)组件,允许用户使用硬件键盘或屏幕键盘输入文本。
TextField(
// 控制器属性,控制正在编辑的文本。
controller: widget.textEditingController,
// 光标颜色属性,绘制光标时使用的颜色。
cursorColor: const Color(0xFFFF6B47),
// 光标宽度属性,光标的厚度,默认是2.0。
cursorWidth: 2.0,
// 样式属性,用于正在编辑的文本的样式。
style: _textFieldStyle,
// 键盘类型属性,用于编辑文本的键盘类型。
keyboardType: TextInputType.number,
// 装饰(`decoration`)属性,在文本字段周围显示的装饰。
// 输入装饰(`InputDecoration`)组件。
decoration: InputDecoration(
// 边框属性,装饰的容器周围绘制的形状。
border: InputBorder.none,
// 填充属性,如果为`true`,则装饰的容器将填充fillColor颜色。
filled: true,
// 填充颜色属性,填充装饰容器的颜色。
fillColor: const Color(0xFFF4F3F4),
// 是密集属性,输入子项是否是密集形式的一部分(即使用较少的垂直空间)。
isDense: true,
// 提示样式属性,用于提示文本(`hintText`)的样式。
hintStyle: _hintStyle,
// 提示文本属性,提示字段接受哪种输入的文本。
hintText: widget.hintText,
),
// 在改变属性,当正在编辑的文本发生更改时调用。
onChanged: (value) {
// 当前文本字段中值的长度。
int fieldValue = value.trim().length;
if (fieldValue == 0) {
inputColor = Color(0xFFC5C5C5);
} else if (fieldValue > widget.maxLength) {
inputColor = Color(0xFFFF3E44);
} else {
inputColor = Color(0xFF00CED2);
}
setState(() {});
// 当前文本字段中值的长度符合给定范围时调用回调函数。
if (fieldValue > widget.minLength-1 && fieldValue < widget.maxLength+1) {
widget.legitimateCallback();
} else {
widget.illegalCallback();
}
},
),
第3步:实现“状态指示条”
最后使用容器(Container
)组件实现2条简单的带颜色的长方形。
// TODO: 第3步:实现“状态指示条”。
Container(
height: 2.0,
color: const Color(0xFF242406),
),
Container(
height: 2.0,
color: inputColor,
),
网友评论