Flutter TextField UI 实例 —— 新手礼包

2024-04-14 1342阅读

Flutter TextField UI 实例 —— 新手礼包

大家好,我是17。

新手礼包一共 3 篇文章,每篇都是描述尽量详细,实例讲解,包会!

  • Flutter Row 实例 —— 新手礼包
  • Flutter TextField UI 实例 —— 新手礼包
  • Flutter TextField 交互实例 —— 新手礼包

    本篇介绍了 TextField UI 的常见写法,从TextField的尺寸,border,icon,文本到光标,无所不包!

    TextField 的尺寸

    默认情况下,TextField 的宽度尽量大,高度包含所有内容并加上 padding。TextField 可以通过 constraints 定义自己的尺寸。

    下面的代码规定了 TextField 最大宽度为 200。

    TextField(
           decoration: InputDecoration(
              constraints: BoxConstraints(maxWidth: 200),
     ));
    

    让 TextFiled 在高度上也尽量大,设置 expands: true,同时还必须设置 maxLines,minLines 为 null。

    TextField(
          maxLines: null,
          minLines: null,
          expands: true,
        );
    

    需要注意在高度上的约束必须是有限的,否则报错。

    Column(
          children: [
              TextField(expands: true,)
          ],
        );
    

    这个例子执行会报错。解决办法看下面的代码:

    Column(
       children: [
         SizedBox(
             height: 200,
             child: TextField(
               expands: true,
               maxLines: null,
               minLines: null,
             )),
         TextField(
           decoration:
               InputDecoration(constraints: BoxConstraints(maxHeight: 200)),
           expands: true,
           maxLines: null,
           minLines: null,
         ),
         Expanded(
             child: TextField(
           expands: true,
           maxLines: null,
           minLines: null,
         ))
       ],
     );
    

    Column 中有三个 TextField,一个用 SizedBox 包起来,一个用 InputDecoration 自带的 constraints 限定,一个用 Expanded 包起来,都是可以的,都可以让 TextField 在高度上的约束是有限的。

    除了 SizedBox,很多 widget 都有修改约束的能力,比如 Container,ConstrainedBox 等。

    Expanded 的解释可以看这篇 Flutter 弹性布局的基石: Flex 和 Flexible。

    默认展示

    第一个示例给出全部代码,贴到 main.dart 就能运行。后面的只给出 TextField 相关。

    Flutter TextField UI 实例 —— 新手礼包
    import 'package:flutter/material.dart';
    void main() => runApp(const MyApp());
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
            home: Scaffold(
                body: Center(child: SizedBox(width: 300, child: MyWidget()))));
      }
    }
    class MyWidget extends StatefulWidget {
      const MyWidget({super.key});
      @override
      State createState() => _MyWidgetState();
    }
    class _MyWidgetState extends State {
      var controller = TextEditingController(text: "IAM17");
      @override
      void dispose() {
        controller.dispose();
        super.dispose();
      } 
      @override
      Widget build(BuildContext context) {
        return Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            TextField(),
            SizedBox(
              height: 20,
            ),
            TextField(),
          ],
        );
      }
    }
    

    没加 Const 关键字,因为反复修改的时候可能得一会删,一会加。发布代码的时候还是应该加上的。

    controller 后面会用到

    用两个 TextField 是为了方便查看 Focus 的效果。上面的为 正常状态的 TextField,下面的为 focus 状态的 TextField。默认配置正常状态下的 TextField 是一条灰线,有焦点的时候变成蓝色。接下来,我们把他变成想要的样子。

    去掉下面的横线

    TextField(  
        decoration: InputDecoration(  
            border: InputBorder.none,  
        ),  
    ),
    

    下面的横线其实就是 border,去掉后,现在只剩下一个光标了。想怎样装扮可以用其它 widget,比如可以用 Container 包起来,自定义 border,也可以用 Row 包起来,加各种图标。这是一个方案,如果你对 TextField 不熟悉,可以这样做来快速完成任务,但实际上,TextField 直接就可以完成大多数装扮,还是用优先用 TextField 自带的装扮为好,因为这样可以少写很多代码。

    实际上,在设置 border: InputBorder.none后还是有 padding 的。为了彻底消除 decoration 的影响,可以把它设置为 null。

    TextField(
         decoration: null,
    );
    

    加边框

    Flutter TextField UI 实例 —— 新手礼包
    TextField(
          decoration: InputDecoration(
            border: OutlineInputBorder(
                gapPadding: 4,
                borderSide: BorderSide(
                    color: Colors.green, width: 2, style: BorderStyle.solid),
                borderRadius: BorderRadius.circular(10)),
          ),
        )
    

    我们给 TextField 加上了宽度为 2,圆角为 10 的边框。

    • width 是用来定义边框的宽度的,可以用小数,比如 1.5
    • style 是线框的样式,目前只有一种可选,就是BorderStyle.solid
    • color 是线框的颜色
    • borderRadius 可以定线框的圆角。
    • gapPadding 定义 labelText 左右的 Padding。

      前面几个都好理解,gapPadding 我再放一个图就明白了。

      gapPadding:4 修改为 100 看下效果。

      Flutter TextField UI 实例 —— 新手礼包

      gapPadding 是作用于 LabelText 的,为 LabelText 的左右添加空白。虽然在视觉上好像是只给右边加了空白,其实左边也加了,只是左边没那么长的线框可以减,看起来好像是少了一小段,其实左边的上边框已经完全减掉了。

      label 也可以拆开写,效果是一样的。

       labelText:  'IAM17',
       labelStyle: TextStyle(color:Color(0xFFC45F84),fontSize: 24),
      

      可能你会想到,要用虚线边框怎么办,需要自定义 decration,本文就不展开说了。

      如果你已经运行了示例代码,会发现 width,color 没有生效?确实是没有生效,线框的颜色还是默认的灰色,宽度还是 1。

      定义线框的颜色和宽度

      定义线框的宽度和颜色不能用 border。InputDecoration 按状态还为我们准备了五种 border,下面示范的是最常用的两种,正常状态下的 enabledBorder,和 focus 状态下的 focusedBorder。

      Flutter TextField UI 实例 —— 新手礼包
      TextField(
             decoration: InputDecoration(
               enabledBorder: OutlineInputBorder(
                 borderRadius: BorderRadius.circular(5),
                 borderSide: BorderSide(
                   color: Colors.green,
                   width: 1.0,
                 ),
               ),
               focusedBorder: OutlineInputBorder(
                 borderRadius: BorderRadius.circular(30),
                 borderSide: BorderSide(
                   color: Color(0xFFC45F84),
                   width: 2.0,
                 ),
               ),
             ),
           )
      

      第三种是 disabledBorder,看效果需要 enabled: false 禁用 TextField。禁用后会展示灰色 border,无法 focus。

      Flutter TextField UI 实例 —— 新手礼包
      TextField(
          decoration: InputDecoration(
            enabled: false,
            disabledBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(5),
              borderSide: BorderSide(
                color: Colors.grey,
                width: 1.0,
              ),
            ),    
          ),
      );
      

      第四种第五种是 error 相关,errorBorder 与 focusedErrorBorder。 给 errorText 赋值,就会触发 TextField 的错误状态。

      Flutter TextField UI 实例 —— 新手礼包
       TextField(
           decoration: InputDecoration(
             errorBorder: OutlineInputBorder(
               borderSide: BorderSide(
                 color: Color.fromARGB(255, 157, 23, 13),
                 width: 1.0,
               ),
             ),
             errorText: '出错了!',
             focusedErrorBorder: OutlineInputBorder(
               borderRadius: BorderRadius.circular(5),
               borderSide: BorderSide(
                 color: Colors.red,
                 width: 2.0,
               ),
             ),
           ),
         )
      

      文本样式,背景色

      Flutter TextField UI 实例 —— 新手礼包
       TextField(
            controller: controller,
            style: TextStyle(color: Color(0xFFC45F84), fontSize: 24),
            decoration: InputDecoration(
                filled: true, fillColor: Color.fromARGB(255, 192, 241, 218)));
      

      controller 在最开始的代码中已经给出来了var controller = TextEditingController(text: "IAM17"); 现在我们用 controller 显示初始文本。

      filled 默认为 false,fillColor 无效,要设置背景色,需要设置 filled: true,然后再设置 fillColor。

      正文文本的样式用 style。可以用 textAlign 控制文本的摆放。我们可以把文本摆放在中间。

      Flutter TextField UI 实例 —— 新手礼包
      TextField(
              textAlign: TextAlign.center,
              controller: controller,
              style: TextStyle(color: Color(0xFFC45F84), fontSize: 24),
              decoration: InputDecoration(
                  filled: true, fillColor: Color.fromARGB(255, 192, 241, 218)))
        ]));
      

      除了可以摆放在中间,还可以摆在末尾,一共有 5 个值可选,具体可以查看 TextAlign

      不够生动?用 icon 和 text 来装扮吧!

      Flutter TextField UI 实例 —— 新手礼包
       TextField(
             controller: controller,
             style: TextStyle(color: Color(0xFFC45F84), fontSize: 24),
             decoration: InputDecoration(
               icon: Icon(Icons.search),
               prefixIcon: Icon(Icons.account_box),
               prefix: Text('你是谁?',
                   style: TextStyle(
                       color: Color.fromARGB(255, 25, 73, 6), fontSize: 20)),
               suffixIcon: Icon(Icons.star),
               suffix: Text('我们见过的',
                   style: TextStyle(
                       color: Color.fromARGB(255, 14, 92, 99), fontSize: 20)),
             ))
      

      内容有点多,把最外面的 Container 的宽度放大到 400。

      一共有五个位置用来装饰。最前面的是 icon,在 border 的外面。接下来是 prefixIcon,然后是正文,最后是 suffix 和 subffixIcon。

      这个五个位置虽然从名字上来看是 Icon 和 Text,但实际上只要是 Widget 都可以!但最好是用 Icon,Text,因为如果用其它 Widget,可能享受不到 Theme 的福利了。

      prefix,suffix 也可以用两个字段替代。

      prefixText: '你是谁?',
      prefixStyle: TextStyle( color: Color.fromARGB(255, 25, 73, 6), fontSize: 20),
      suffixText: '我们见过的',
      suffixStyle: TextStyle( color: Color.fromARGB(255, 14, 92, 99), fontSize: 20),
      

      扩写和缩写只能采用一种,同时存在会报错!

      自定义 Icon 的颜色

      当前 Icon 的 color 都是默认的,如何修改 Icon 的颜色呢?可能你第一时间想到这样修改:

      icon: Icon(Icons.search,color:Colors.green),
      

      你一定很高兴,it work! 现在 TextField 的正常状态和 foucs 状态的颜色都是 green。那么,如果想让 TextField 的 focus 状态的 icon 颜色是红色,怎么办?

      思考中…

      好像很棘手,其实 Flutter 已经为我们设计好了如何修改 Icon 的颜色,用 Theme!

      首先定义一个 MaterialStateColor。

      class IconColor extends MaterialStateColor {
        const IconColor() : super(_defaultColor);
        //绿色
        static const int _defaultColor = 0xff00ff00;
        //红色
        static const int _focusColor = 0xffff0000;
        @override
        Color resolve(Set states) {
          if (states.contains(MaterialState.focused)) {
            return const Color(_focusColor);
          }
          return const Color(_defaultColor);
        }
      }
      

      然后加入到 Theme 中,我们需要修改一下之前的代码。

      MaterialApp(
         theme: ThemeData(
            inputDecorationTheme: InputDecorationTheme(
               iconColor: IconColor()
             ),),
         home: Scaffold(
             body: Center(child: SizedBox(width: 400, child: MyWidget()))));
      

      查看效果默认的时候 icon 是绿色的,focus 的时候是红色的。

      Flutter TextField UI 实例 —— 新手礼包

      如果你觉得定义一个类太麻烦,也可以用 resolveWith 方法

      MaterialApp(
          theme: ThemeData(
            inputDecorationTheme: InputDecorationTheme(iconColor:
                MaterialStateColor.resolveWith((Set states) {
              if (states.contains(MaterialState.focused)) {
                return Colors.red;
              }
              return Colors.green;
            })),
          ),
          home: Scaffold(
              body: Center(child: SizedBox(width: 300, child: MyWidget()))));
      

      前面说的 border, 也可以通过 Theme 设置。这样就不用每个 TextField 都定一遍了!

      inputDecorationTheme: InputDecorationTheme(
               enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.green)),
               focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.red))
       )
      

      inputDecorationTheme 可以设置很多内容。Theme 相当于是 css 中的样式表。Theme 如果写在 MaterialApp 中,就相当于是全局样式表了,写在其它地方相当于局部样式表。子级的 Theme 的优先级大于父级的 Theme。写在 Widget 里的相当于 Style,优先级最高。

      isDense

      上面是默认 isDense:false 的效果,下面是 isDense:true 的效果,就是icon变小了一些。

      Flutter TextField UI 实例 —— 新手礼包
      InputDecoration(
           isDense: true,
           icon: Icon(Icons.search),
           prefixIcon: Icon(Icons.account_box),
           prefix: Text('你是谁?',
               style: TextStyle(
                   color: Color.fromARGB(255, 25, 73, 6), fontSize: 20)),
           suffixIcon: Icon(Icons.star),
           suffix: Text('我们见过的',
               style: TextStyle(
                   color: Color.fromARGB(255, 14, 92, 99), fontSize: 20)),
         );
      

      hint text 与 helper text

      灰色的是 hintText,和 html 中 placeholder 差不多。绿色的是 helper Text,显示在左下角。

      Flutter TextField UI 实例 —— 新手礼包
      TextField(
         decoration: InputDecoration(
           hintText: 'IAM17',
           hintStyle: TextStyle(color: Colors.black54),
           hintMaxLines: 1,
           helperText: '我们见过的',
           helperStyle: TextStyle(color: Color.fromARGB(255, 52, 116, 7)),
           helperMaxLines: 1,
         ))
      

      已经包含 hint text 与 helper text 的所有属性了,比较好理解,就不再解释了。要注意的一点是:focus 对这两个 text 的样式没有影响。error 状态 hint text 没有变化,helper text 被 errorText 取代。

      label text

      同时有 label text 和 hint text 的时候,正常状态下会优先显示 labelText。在 focus 状态下,labelText 缩小到左上角,hint text 显示出来。

      Flutter TextField UI 实例 —— 新手礼包

      label text 远没有这么简单,除 labelText,labelStyle,还有几个属性需要了解。

      floatingLabelStyle 定义 focus 状态下 label 显示在左上角的样式。正常状态下 label text 的颜色用 labelStyle 设置为灰色,浮到左上角后可以用 floatingLabelStyle 设置为绿色。

      Flutter TextField UI 实例 —— 新手礼包
      TextField(
          decoration: InputDecoration(
            labelText: '你是谁',
            labelStyle: TextStyle(color: Colors.grey),
            floatingLabelStyle: TextStyle(color: Colors.green),
          ))
      )
      

      floatingLabelAlignment 可以让左上角的 label 显示在中间。(只有 start 和 center 两个选项)

      Flutter TextField UI 实例 —— 新手礼包
      TextField(
         decoration: InputDecoration(
           labelText: '你是谁',
           labelStyle: TextStyle(color: Color.fromARGB(255, 194, 52, 101)),
           floatingLabelStyle: TextStyle(color: Colors.blue),
           floatingLabelAlignment: FloatingLabelAlignment.center
         ));
      

      floatingLabelBehavior 控制 label 的行为,有三个选项

      • FloatingLabelBehavior.auto 默认。正常状态覆盖 hint,focus 状态上浮。
      • FloatingLabelBehavior.always 正常状态 和 focus 状态 都上浮。hint 正常显示。
      • FloatingLabelBehavior.never 正常状态覆盖 hint,focus 状态不上浮。这时就和 hint 并不多了,唯一不同的是 focus 的时候 hint 不消失,label 消失。

        padding

        默认情况下,在正文的四周是有 padding 的。

        Flutter TextField UI 实例 —— 新手礼包

        contentPadding: EdgeInsets.zero 可以去掉左右的 padding。

        Flutter TextField UI 实例 —— 新手礼包
        decoration: InputDecoration(
            contentPadding: EdgeInsets.zero,
            filled: true,
            fillColor: Color.fromARGB(255, 192, 241, 218)))
        

        去掉上下的 padding 要用到一个属性,isCollapsed可以把上下左右的 padding 都去掉。

        Flutter TextField UI 实例 —— 新手礼包
        InputDecoration(
            isCollapsed: true,
            filled: true,
            fillColor: Color.fromARGB(255, 192, 241, 218))
        

        也可以用InputDecoration.collapsed,但要求必须指定 hintText,不允许再指定 labelText,errorText,icon。

        InputDecoration.collapsed(
           hintText: "你是谁",
           filled: true,
           fillColor: Color.fromARGB(255, 192, 241, 218))
        

        直接用 isCollapsed: true,可以指定 labelText,errorText,icon,但 UI 上可能不大理想,所以如果想去掉所有 padding,优先用 InputDecoration.collapsed。

        自定义光标

        可以自定义光标的宽度,radius,和颜色。

        Flutter TextField UI 实例 —— 新手礼包
        TextField(
             cursorWidth: 16.0,
             cursorRadius: Radius.circular(18.0),
             cursorColor: Color(0xFFC45F84),
           ),
        

        Flutter TextField UI 常见写法到这里就结束了,谢谢观看。

        欢迎观看下一篇 Flutter TextField 交互实例 —— 新手礼包

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]