【Flutter 专题】65 图解基本 TextField 文本输入框 (二)

网友投稿 863 2022-05-29

小菜刚学习了 TextField 的基本用法,今天特意学习一下 TextField InputDecoration 文本框装饰器的相关内容;

InputDecoration 源码分析

const InputDecoration({ this.icon, // 装饰器外小图标 this.labelText, // 文本框描述标签 this.labelStyle, // 文本框描述标签样式 this.helperText, // 文本框辅助标签 this.helperStyle, // 文本框辅助标签样式 this.hintText, // 文本框默认提示信息 this.hintStyle, // 文本框默认提示信息样式 this.hintMaxLines, // 文本框默认提示信息最大行数 this.errorText, // 文本框错误提示信息 this.errorStyle, // 文本框错误提示信息样式 this.errorMaxLines, // 文本框错误提示信息最大行数 this.hasFloatingPlaceholder = true, // 文本框获取焦点后 labelText 是否向上浮动 this.isDense, // 是否问紧凑型文本框 this.contentPadding, // 文本内边距 this.prefixIcon, // 前置图标 this.prefix, // 前置预填充 Widget this.prefixText, // 前置预填充文本 this.prefixStyle, // 前置预填充样式 this.suffixIcon, // 后置图标 this.suffix, // 后置预填充 Widget this.suffixText, // 后置预填充文本 this.suffixStyle, // 后置预填充样式 this.counter, // 输入框右下角 Widget this.counterText, // 输入框右下角文本 this.counterStyle, // 输入框右下角样式 this.filled, // 是否颜色填充文本框 this.fillColor, // 填充颜色 this.errorBorder, // errorText 存在时未获取焦点边框 this.focusedBorder, // 获取焦点时边框 this.focusedErrorBorder, // errorText 存在时获取焦点边框 this.disabledBorder, // 不可用时边框 this.enabledBorder, // 可用时边框 this.border, // 边框 this.enabled = true, // 输入框是否可用 this.semanticCounterText, this.alignLabelWithHint, // 覆盖将标签与 TextField 的中心对齐 }) const InputDecoration.collapsed({ @required this.hintText, this.hasFloatingPlaceholder = true, this.hintStyle, this.filled = false, this.fillColor, this.border = InputBorder.none, this.enabled = true, })

分析源码可知,flutter 不仅提供了全面的构建装饰器的方式,还提供了简单便利的构建方式 collapsed 默认是无边框的,且无法设置标签等其他属性;

案例尝试

icon 为装饰器外小图标,可灵活设置图标或其他 Widget,默认距输入框 16dp,主题可通过 IconTheme 设置;

return TextField(decoration: InputDecoration(icon: Image.asset('images/ic_launcher.png'))); return TextField(decoration: InputDecoration(icon: Icon(Icons.android)));

labelText 为文本框描述标签,为 String 类型,直接编辑内容即可;labelStyle 为标签样式属性;TextField 获取焦点之后描述标签上移;

return TextField(decoration: InputDecoration( labelText: '用户名:', labelStyle: TextStyle(color: Colors.purple)));

helperText 为文本框辅助标签,一般在文本框底部,提示性内容;helperStyle 为文本框辅助标签样式属性;与 TextField 是否获取焦点无变化;

【Flutter 专题】65 图解基本 TextField 文本输入框 (二)

return TextField(decoration: InputDecoration( labelText: '用户名:', labelStyle: TextStyle(color: Colors.purple), helperText: '请输入手机号或邮箱!', helperStyle: TextStyle(color: Colors.teal)));

hintText 为文本框默认提示信息,若设置 labelText,则 TextField 在未获取焦点时优先展示 labelText;hintStyle 为文本框提示信息样式属性;hintMaxLines 为提示信息过长时允许展示的最大行数;

return TextField(decoration: InputDecoration( hintStyle: TextStyle(color: Colors.brown), hintMaxLines: 1, hintText: '请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!')); return TextField(decoration: InputDecoration( labelText: '用户名:', labelStyle: TextStyle(color: Colors.purple), helperText: '请输入手机号或邮箱!', helperStyle: TextStyle(color: Colors.teal), hintText: '请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!', hintStyle: TextStyle(color: Colors.brown), hintMaxLines: 2));

errorText 为文本框错误提示信息,一般在文本框底部,当设置 errorText 时不展示 helperText,整体默认为红色;errorStyle 为错误提示信息样式属性;errorMaxLines 为错误信息过长时允许展示的最大行数;与 hintText 类似;

return TextField(onChanged: (text) { setState(() { _textLength = text.length; }); }, decoration: InputDecoration( labelText: '用户名:', labelStyle: TextStyle(color: Colors.purple), helperText: '请输入手机号或邮箱!', helperStyle: TextStyle(color: Colors.teal), hintText: '请输入用户名信息!', hintStyle: TextStyle(color: Colors.brown), errorText: _textLength > 11 ? '请勿超过 11 位用户名!' : null, errorStyle: TextStyle(color: Colors.pink)));

hasFloatingPlaceholder 设置 TextField 获取焦点时 labelText 是否向上浮动;设置为 false 时,获取焦点后 labelText 隐藏,不会向上浮动;

return TextField(decoration: InputDecoration(labelText: '用户名:', labelStyle: TextStyle(color: Colors.purple), hasFloatingPlaceholder: false));

isDense 是否为紧凑型文本框,true 为紧凑型文本框,图标等与输入框边距较小;

return TextField(decoration: InputDecoration(icon: Icon(Icons.android), isDense: false)); return TextField(decoration: InputDecoration(icon: Icon(Icons.android), isDense: true));

contentPadding 为编辑内容与文本框内边距;

returnTextField(decoration: InputDecoration(contentPadding: EdgeInsets.all(20.0)));

prefix… 是文本框前置组件,prefixIcon 为前置图标,固定在文本输入框前边,与 icon 位置不同,其样式通过 IconTheme 调整;prefixText 为前置预填充文本,例如手机号前(+86) 之类;prefix 为前置预填充组件,可自由设置,更为灵活,但不能与 prefixText 同时使用;prefixStyle 为预填充组件样式;

return TextField(decoration: InputDecoration( prefixIcon: Icon(Icons.supervised_user_circle), prefixText: '(+86)', prefixStyle: TextStyle(color: Colors.purple.withOpacity(0.4)))); return TextField(decoration: InputDecoration( prefixIcon: Icon(Icons.supervised_user_circle), prefixStyle: TextStyle(color: Colors.purple.withOpacity(0.4)), prefix: Row(mainAxisSize: MainAxisSize.min, children: [Icon(Icons.phone), Text('(+86)')])));

suffix… 为文本框后置组件系列;与 prefix… 用法一致;

return TextField(decoration: InputDecoration( suffixIcon: Icon(Icons.close), suffixText: '关闭', suffixStyle: TextStyle(color: Colors.purple.withOpacity(0.4)))); return TextField(decoration: InputDecoration( suffixIcon: Icon(Icons.close), suffixStyle: TextStyle(color: Colors.purple.withOpacity(0.4)), suffix: Row(mainAxisSize: MainAxisSize.min, children: [Text('关闭'), Icon(Icons.remove_red_eye)])));

counter 系列为文本框右下角计数器,当设置 maxLengths 时通常会在右下角展示编辑字符数与整体数量比,可通过 counter 系列组件调整;counterText 为计数器展示内容;counterStyle 为计数器样式属性;

return TextField(maxLength: 20, decoration: InputDecoration(counterText: '最大长度不超过20', counterStyle: TextStyle(color: Colors.blueAccent)));

filled 为文本框是否颜色填充,只有 true 时,filledColor 才生效;

return TextField(decoration: InputDecoration(fillColor: Colors.green.withOpacity(0.4), filled: true));

enabled 为文本框是否可用,false 为不可用,无法获取焦点;

return TextField(decoration: InputDecoration(enabled: false));

alignLabelWithHint 用于 TextField 设置多行时,true 时覆盖将标签与 TextField 的中心对齐的默认行为,小菜尝试了多种情况下 true 和 false 状态,发现效果并不明显,有待继续研究;

return TextField(maxLines: null, decoration: InputDecoration( alignLabelWithHint: true, labelText: '用户名:', hintMaxLines: null, helperText: '请输入手机号或邮箱!', hintText: '请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!请输入用户名信息!', ));

border 为一个系列,包括各种环境下边框;默认 border 为正常状态下边框;边框基本包括三类:

a. InputBorder 一般设置为无边框样式;

return TextField(decoration: InputDecoration(border: InputBorder.none));

b. UnderlineInputBorder 一般设置为底部一条直线边框样式;小菜测试时设置边框圆角为 10dp 加上背景色效果更明显;

return TextField(decoration: InputDecoration( filled: true, fillColor: Colors.green.withOpacity(0.4), border: UnderlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple, width: 4.0, style: BorderStyle.solid))));

c. OutlineInputBorder 一般设置为包围的圆角边框;相较于 UnderlineInputBorder 多了 gapPadding 属性,用于浮动的 labelText 与边框的间距;

return TextField(decoration: InputDecoration( labelText: '用户名:', labelStyle: TextStyle(color: Colors.purple), border: OutlineInputBorder( gapPadding: 10.0, borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple, width: 4.0, style: BorderStyle.solid))));

小菜测试发现 UnderlineInputBorder 和 OutlineInputBorder 对于设置 border 边框颜色无效,需要通过 ThemeData 来更改属性;

enabledBorder 为可用时边框样式,enabled 为 true;

Tips:

errorText 存在时 enabledBorder 不生效;

若不设置其他 border 属性,获取焦点默认是 ThemeData 中焦点边框,设置 border 或 focusedBorder 等生效;

// UnderlineInputBorder 类型且只设置 enabledBorder return TextField(decoration: InputDecoration(filled: true,fillColor: Colors.green.withOpacity(0.4), enabledBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple, width: 4.0)))); // UnderlineInputBorder 类型且设置 enabledBorder 和 border return TextField(decoration: InputDecoration(filled: true, fillColor: Colors.green.withOpacity(0.4), enabledBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple, width: 4.0)), border: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0))))); // UnderlineInputBorder 类型且 errorText 不为空 return TextField(decoration: InputDecoration(filled: true, fillColor: Colors.green.withOpacity(0.4), errorText: '请勿超过 11 位!', errorStyle: TextStyle(color: Colors.pink), enabledBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple, width: 4.0)), border: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0))))); // OutlineInputBorder 类型且只设置 enabledBorder return TextField(decoration: InputDecoration(labelText: '用户名:', labelStyle: TextStyle(color: Colors.purple), enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple.withOpacity(0.4), width: 3.0)), border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0))))); // OutlineInputBorder 类型设置 enabledBorder,且 errorText 不为空 return TextField(decoration: InputDecoration(labelText: '用户名:', labelStyle: TextStyle(color: Colors.purple), errorText: '请勿超过 11 位!', errorStyle: TextStyle(color: Colors.pink), enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple.withOpacity(0.4), width: 3.0)))); // OutlineInputBorder 类,设置 enabledBorder 和 border 且 errorText 不为空 return TextField(decoration: InputDecoration(labelText: '用户名:', labelStyle: TextStyle(color: Colors.purple), errorText: '请勿超过 11 位!', errorStyle: TextStyle(color: Colors.pink), enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple.withOpacity(0.4), width: 3.0)), border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)))));

disabledBorder 为不可用时边框,enabled 为 false;且 errorText 存在时 disabledBorder 不生效;

// UnderlineInputBorder 类型 return TextField( decoration: InputDecoration(enabled: false, filled: true, fillColor: Colors.green.withOpacity(0.4), disabledBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.pink, width: 4.0)))); // UnderlineInputBorder 类型且设置 errorText return TextField(decoration: InputDecoration(enabled: false, filled: true, fillColor: Colors.green.withOpacity(0.4), errorText: '请勿超过 11 位!', errorStyle: TextStyle(color: Colors.pink), disabledBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.pink, width: 4.0))); // OutlineInputBorder 类型 return TextField(decoration: InputDecoration(enabled: false, labelText: '用户名:', labelStyle: TextStyle(color: Colors.purple), disabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.green, width: 4.0)))); // OutlineInputBorder 类型且设置 errorText return TextField(decoration: InputDecoration(enabled: false, labelText: '用户名:', labelStyle: TextStyle(color: Colors.purple), errorText: '请勿超过 11 位!', errorStyle: TextStyle(color: Colors.pink), disabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.pink, width: 4.0))));

focusedBorder 为获取焦点时边框,errorText 存在时 focusedBorder 不生效;

// UnderlineInputBorder 类型 return TextField(decoration: InputDecoration( filled: true, fillColor: Colors.green.withOpacity(0.4), focusedBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.pink, width: 4.0)), enabledBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple, width: 4.0)))); // UnderlineInputBorder 类型且设置 errorText return TextField(decoration: InputDecoration( filled: true, fillColor: Colors.green.withOpacity(0.4), errorText: '请勿超过 11 位!', errorStyle: TextStyle(color: Colors.pink), focusedBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.pink, width: 4.0)), enabledBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple, width: 4.0)))); // OutlineInputBorder 类型 return TextField(decoration: InputDecoration( labelText: '用户名:', labelStyle: TextStyle(color: Colors.purple), enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple.withOpacity(0.4), width: 3.0)), focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.green, width: 4.0)))); // OutlineInputBorder 类型且设置 errorText return TextField(decoration: InputDecoration( labelText: '用户名:', labelStyle: TextStyle(color: Colors.purple), errorText: '请勿超过 11 位!', errorStyle: TextStyle(color: Colors.pink), focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.pink, width: 4.0)), enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple.withOpacity(0.4), width: 3.0))));

errorBorder 为 errorText 不为空且未获取焦点时边框;

// UnderlineInputBorder 类型 return TextField(decoration: InputDecoration( filled: true, fillColor: Colors.green.withOpacity(0.4), errorText: '请勿超过 11 位!', errorStyle: TextStyle(color: Colors.pink), errorBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.black.withOpacity(0.4), width: 4.0)))); // OutlineInputBorder 类型 return TextField(decoration: InputDecoration( labelText: '用户名:', labelStyle: TextStyle(color: Colors.purple), errorText: '请勿超过 11 位!', errorStyle: TextStyle(color: Colors.pink), errorBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.black.withOpacity(0.4), width: 3.0))));

focusedErrorBorder 为 errorText 不为空且获取焦点时边框;

// UnderlineInputBorder 类型 return TextField(decoration: InputDecoration( filled: true, fillColor: Colors.green.withOpacity(0.4), errorText: '请勿超过 11 位!', errorStyle: TextStyle(color: Colors.pink), focusedErrorBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.teal, width: 4.0)), errorBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.black, width: 4.0)))); // OutlineInputBorder 类型 return TextField(decoration: InputDecoration( labelText: '用户名:', labelStyle: TextStyle(color: Colors.purple), errorText: '请勿超过 11 位!', errorStyle: TextStyle(color: Colors.pink), focusedErrorBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.pink, width: 4.0)), errorBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple.withOpacity(0.4), width: 3.0))));

小扩展

在实际开发中,可能回随时需要关闭键盘,此时我们仅需监听一下即可;小菜监听一个文本输入框,当输入字符长度大于 11 位时即收起键盘;

return TextField(controller: controller, decoration: InputDecoration( labelText: '用户名:', labelStyle: TextStyle(color: Colors.purple), errorText: '请勿超过 11 位!', errorStyle: TextStyle(color: Colors.pink))); void initState() { super.initState(); controller.addListener(() { setState(() { if (controller.text.length >= 11) { // 收起键盘 FocusScope.of(context).requestFocus(FocusNode()); } }); }); }

文本输入框确实有很多细节需要研究和尝试,小菜仅初步了解,有待深入研究;且小菜建议时常升级 Flutter 版本,可能对于同一个 Widget 会有或多或少的更新,如有问题请多多指导!

来源: 阿策小和尚

Flutter

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:redis——事务
下一篇:《AI安全之对抗样本入门》—2.10 GPU服务器
相关文章