【Flutter】深入剖析TextField组件

Flutter速来系列6: Flutter同学 输入框TextField就算了,还整个表单? Flutter的输入框是常见的用户界面组件之一,用于接收用户的文本输入。Flutter提供了TextField组件来创建输入框,并提供了许多属性来定制输入框的外观和行为。本文将详细介绍Flutter的输入框,并解释常用属性的作用,提供具体代码示例,并讨论自定义输入框样式和日常开发中需要注意的事项。 阅读详情

前言

在之前学习和使用Flutter过程中肯定会频繁使用到TextField组件。而且在此过程中也频繁出现使用输入框遇到的坑:布局、高度问题、TextField在iOS平台输入中文、## TextField获取/失去焦点以及软键盘获取。

总结这些问题之后就更需要深入了解Flutter平台中TextField的使用和源码剖析。

属性值

TextField组件本身具备多种属性,支持很多参数设置来实现不同样式效果。 TextField组件可直接上手使用,但默认样式和输入规则并不一定是需求开发中想要的(实话说默认样式并不好看)。下面就通过TextField组件属性介绍来自定义属于自己的输入框吧。

TextField(); 

基础功能

  • obscureText: true表示隐藏输入内容,类似密码输入
  • readOnly: true表示输入框禁止输入
  • textCapitalization:控制输入内容大小写(words 首字母大写、sentences 句子首字母大写、characters 所有字母大写),可能存在兼容性问题会不生效。
  • minLines & maxLines: 最小行数和最大行数设置,若只设置最大行数输入框高度就是maxLines的高度,否则是minLines的高度。
  • maxLength: 输入字符限制器。在输入框下方会出现输入字符数量(一般也不希望透出计数)

样式

样式设置主要未然光标和输入框装饰内容设置。

光标

光标支持自定义,支持设置颜色、高度、宽度、圆角以及是否展示光标。

cursorColor:  Colors.black,
cursorHeight:  10,
cursorWidth: 5,
cursorRadius: Radius.circular(10),
showCursor: false, 
装饰

前面提到输入框默认样式比较普通,日常开发中需要设置输入框样式。自定义输入框样式是可以通过decoration来实现的。

  • 外框

外框可以使用内置官方已有样式,也能通过自定义边框来实现。

decoration: InputDecoration(
  border: OutlineInputBorder()
) 
  • hint提示

默认未输入内容的提示信息

decoration: InputDecoration(
  hintText: "请输入"
) 
  • 悬浮提示

悬浮提示就是当获取焦点后的输入信息的提示(不太常用)

decoration: InputDecoration(
  lableText: "请输入"
) 

另外InputDecoration还支持设置其他border,例如错误状态、获取交点状态、不可用状态等都能自定义。

软键盘

  • textInputAction: 软键盘按钮样式和功能设置(none、unspecified、done、go、search、next等)实现软键盘按钮不同操作能力。
  • focusNode: 控制焦点使用,通过它实现弹起或收起软键盘能力。
  • autofocus: 是否主动获取焦点,true时在初始化后会自动获取焦点并弹起软键盘(一般情况下是会弹起,特殊情况除外)

输入控制

获取输入内容的方式有两种:onChanged和controller。

  • onChanged
TextField(
    onChanged:(text){
        // 这个可以返回输入文本
    }
) 
  • controller
TextEditingController controller = TextEditingController();
controller.addListener((){
    // 这个可以返回输入文本
    controller.text;
});
TextField(
    controller: controller,
) 
  • inputFormatters: 输入字符限制,通过自定义限制输入内容。

这里举例内置的LengthLimitingTextInputFormatter用来限制输入字符数。这和基础功能中maxLength是一样的作用,不同点在于maxLength会携带计数器。

源码解析

TextField继承StatefulWidget,所以就直接来看_TextFieldState

_TextFieldState

_TextFieldState中的build方法中实现输入框的展示。在内部多层组件嵌套下(FocusTrapArea、MouseRegion等)核心是EditableText组件。 另外在build方法中还有switch (theme.platform)方法,由于各个平台中对于输入框的实现存在差异,例如安卓和iOS输入框的光标以及选择状态样式存在差异。因此这里的switch (theme.platform)主要就是对于平台差异性做一些设置,代码可见主要是光标和textSelectionControls文本选择上有所不同。

switch (theme.platform) {
  case TargetPlatform.iOS:
    final CupertinoThemeData cupertinoTheme = CupertinoTheme.of(context);
    forcePressEnabled = true;
    textSelectionControls ??= cupertinoTextSelectionControls;
    paintCursorAboveText = true;
    cursorOpacityAnimates = true;
    cursorColor ??= selectionTheme.cursorColor ?? cupertinoTheme.primaryColor;
    selectionColor = selectionTheme.selectionColor ?? cupertinoTheme.primaryColor.withOpacity(0.40);
    cursorRadius ??= const Radius.circular(2.0);
    cursorOffset = Offset(iOSHorizontalOffset / MediaQuery.of(context).devicePixelRatio, 0);
    autocorrectionTextRectColor = selectionColor;
    break;
    ......
  case TargetPlatform.android:
  case TargetPlatform.fuchsia:
    forcePressEnabled = false;
    textSelectionControls ??= materialTextSelectionControls;
    paintCursorAboveText = false;
    cursorOpacityAnimates = false;
    cursorColor ??= selectionTheme.cursorColor ?? theme.colorScheme.primary;
    selectionColor = selectionTheme.selectionColor ?? theme.colorScheme.primary.withOpacity(0.40);
    break; 

EditableTextState

_TextFieldState中平台差异性判断之后,接下来就是EditableText组件内部。同样EditableText是继承自StatefulWidget,略过之后直接看EditableTextState。在build方法中同样是通过多层嵌套(MouseRegion、Scrollable、CompositedTransformaTarget)去看更主要的_Editable。

_Editable

_Editable是继承自MultiChildRenderObjectWidget,绝大多数布局控件都是继承MultiChildRenderObjectWidget实现的。_Editable实现的渲染对象是RenderEditable

RenderEditable

RenderEditable就是RenderBox,就到了底层布局的测量、绘制、更新的过程。源码分析就直接看paint方法实现。

_paintContents部分是绘制文本内容,内部由TextPainter对文本绘制的实现。

@override
void paint(PaintingContext context, Offset offset) {
  _computeTextMetricsIfNeeded();
  if (_hasVisualOverflow && clipBehavior != Clip.none) {
    _clipRectLayer.layer = context.pushClipRect(
      needsCompositing,
      offset,
      Offset.zero & size,
      _paintContents,
      clipBehavior: clipBehavior,
      oldLayer: _clipRectLayer.layer,
    );
  } else {
    _clipRectLayer.layer = null;
    _paintContents(context, offset);
  }
  _paintHandleLayers(context, getEndpointsForSelection(selection!));
} 

_paintHandleLayers是文本选择器的绘制,若endpoints == 2则是段落选择。否则只是单选就只有一个光标选择。

void _paintHandleLayers(PaintingContext context, List<TextSelectionPoint> endpoints) {
  Offset startPoint = endpoints[0].point;
  startPoint = Offset(
    startPoint.dx.clamp(0.0, size.width),
    startPoint.dy.clamp(0.0, size.height),
  );
  context.pushLayer(
    LeaderLayer(link: startHandleLayerLink, offset: startPoint),
    super.paint,
    Offset.zero,
  );
  if (endpoints.length == 2) {
    Offset endPoint = endpoints[1].point;
    endPoint = Offset(
      endPoint.dx.clamp(0.0, size.width),
      endPoint.dy.clamp(0.0, size.height),
    );
    context.pushLayer(
      LeaderLayer(link: endHandleLayerLink, offset: endPoint),
      super.paint,
      Offset.zero,
    );
  }
} 

最后

如果你进阶的路上缺乏方向,可以扫描下方二维码加入我们的圈子和安卓开发者们一起学习交流!
以下全部内容都可以在微信中获取!

  • Android进阶学习全套手册

    img

最后,借用我最喜欢的乔布斯语录,作为本文的结尾:

人这一辈子没法做太多的事情,所以每一件都要做得精彩绝伦。
你的时间有限,所以不要为别人而活。不要被教条所限,不要活在别人的观念里。不要让别人的意见左右自己内心的声音。
最重要的是,勇敢的去追随自己的心灵和直觉,只有自己的心灵和直觉才知道你自己的真实想法,其他一切都是次要。

Flutter TextField自动读取剪切板的安全隐患与解决方案 本文深入剖析了Flutter应用中TextField组件在初始化时自动读取系统剪切板的安全隐患。该行为由框架底层ClipboardStatusNotifier触发,可能导致用户隐私数据在无感知情况下泄露。文章提供了两种解决方案:修改Flutter源码或通过Hook拦截Platform Channel通信,并重点推荐了适用于混合开发场景的非侵入式Hook方案,以平衡功能与隐私合规要求。 阅读详情

相关推荐

Flutter TextField自动读取剪切板?手把手教你如何避免合规风险

本文深入探讨了Flutter TextField自动读取剪切板带来的合规风险,并提供了工程化解决方案。通过分析Flutter引擎的自动化陷阱,文章详细介绍了源码拦截法和Widget层封装两种方法,帮助开发者避免隐私违规问题,确保应用合规运行。

weixin_28717467的博客 147

Flutter文本输入框TextField属性(InputDecoration、textInputAction、inputFormatters等等)详解

TextField 构造方法:

喻志强的博客 12万+

Flutter剪切板访问的那些坑:从TextField源码到实战避坑指南

本文深入剖析了Flutter应用中TextField组件在初始化时自动访问系统剪切板的机制与合规风险。通过追踪源码,揭示了其隐式触发链路,并提供了从自定义Controller、封装安全组件到平台通道拦截等四种实战避坑方案,帮助开发者有效规避隐私合规问题。

weixin_29016833的博客 314

Flutter——最详细(TextField)使用教程

文本输入框,拥有复杂的属性。可指定控制器、文字样式、装饰线、行数限制、游标样式等。监听输入框变动事件。

人生在世 9272

Flutter TextField自动读取剪切板的隐患与解决方案

本文深入分析了Flutter TextField组件自动读取剪切板内容的安全隐患,揭示了其底层实现机制及可能引发的隐私合规风险。针对这一问题,提供了原生层拦截、Flutter层自定义组件等实用解决方案,并给出最佳实践建议,帮助开发者确保应用符合隐私保护要求。

weixin_28717411的博客 304

Flutter | 快速实现TextField长按菜单本地化(中文复制/粘贴)

本文详细介绍了如何为Flutter应用的TextField组件实现长按菜单的本地化,将默认的英文选项(如“Copy”)转换为中文(如“复制”)。核心解决方案是通过在MaterialApp中配置localizationsDelegates和supportedLocales,仅需几行代码即可快速生效。文章还涵盖了多语言支持、自定义菜单内容及iOS环境下的注意事项等进阶实践。

weixin_29007809的博客 353

Flutter - TextField

TextField用于文本输入

a136447572的专栏 1546

Flutter TextField数字输入限制保姆级教程:从正则到键盘类型,一次搞定

本文提供Flutter TextField数字输入限制的全面指南,从基础设置到高级正则表达式过滤,涵盖键盘类型、inputFormatters和TextEditingController的使用。通过详细代码示例和边界情况处理,帮助开发者实现健壮的数字输入功能,优化用户体验。

weixin_28693309的博客 406

Flutter 快速解析 TextField 的内部原理

看完本篇,你不仅会了解到 TextField 的实现和构成,还可以学到很多之前不常用的“奇怪”知识。 在 Flutter 里 TextField 是一个比较复杂的控件,而在整个 TextField 里嵌套了许多不同实现的控件,它们组成了我们常用的输入框效果,如下图所示是关于 TextField 的主要构成部分,也是本篇主要讲解的内容。 FocusTrapArea FocusTrapArea 大家可能会比较陌生,这个是最近的版本里才出现的控件,FocusTrapArea 本身并没有特别,它仅仅是在 Re.

恋猫de小郭的博客 2932

Flutter TextField详解

文章目录基本属性TextFieldInputDecoration样式基础样式隐藏文本键盘类型键盘按钮大小写光标最多行数计数器图标提示文字去除下划线边框获取输入内容关闭软键盘校验异常总结github:https://github.com/yechaoa/wanandroid_flutter/blob/master/lib/pages/loginPage.dart 效果: 终于还是对TextFie...

yechaoa 5万+

flutter TextField换行自适应的实现

无论哪种界面框架输入文本框都是非常重要的控件, 但是发现flutter中的输入框TextField介绍的虽然多,但是各个属性怎么组合满足需要很多文章却说不清楚, 再加上控件版本变更频繁很多功能的介绍都是比较陈旧的属性.现在就需要一个类似微信的输入文本框, 这样一个非常实用的效果flutter要如何实现?前提是尽量用已有属性,少写或不写代码. 先明确这种输入文本框有哪些功能点? 能够自定义各种间距.主要是控件外边距(margin); 内间距(padding); 能够自定义样式. 输入框边框(圆角(radius),描边(border),颜色); 字样(大小,颜色), 提示字样(hint);

Flutter 快速解析 TextField 的内部原理 | 开发者说·DTalk

本文原作者: 恋猫de小郭,原文发布于: GSYTech看完本篇,您不仅会了解到 TextField 的实现和构成,还可以学到很多之前不常用的"奇怪"知识。在 Flutter 里Te...

谷歌开发者 553

将Python爬取的数据导入钉钉多维表

摘要:本文介绍将Python爬取的数据导入钉钉多维表的完整解决方案。首先通过requests库爬取数据并解析为结构化格式,然后使用钉钉开放平台API对接多维表。关键步骤包括获取app_key、app_secret等凭证,通过OAuth2获取access_token,以及批量写入记录。文章详细说明了参数获取位置、字段类型匹配、权限配置等注意事项,并提供了错误处理建议和性能优化方法。适用于需要将网络数据同步到钉钉多维表的开发场景。

IT深耕十余载,大道之简 2131

Flutter 基础 Widget 全面指南:从布局原理到工程实践与性能优化

在跨端应用开发中,界面构建方式直接决定了项目的可维护性与运行性能。Flutter 作为一套由 Google 推出的 UI 框架,以“一切皆 Widget”的组合式设计闻名,开发者通过嵌套轻量级的描述对象即可搭建出完整界面。其底层由 Element 树与 RenderObject 树负责真正的绘制与更新,而 Widget 本身只作为不可变的配置蓝图,这种机制既保证了渲染效率,也赋予了框架极高的灵活性。理解 Widget 的不可变特性、组合方式以及常见的基础组件,如 Container、Row、Column、S

weixin_34221654的博客 198

Vivado新手避坑指南:搞懂Generate Output Products和Create HDL Wrapper到底在干啥

本文深入解析Vivado设计流程中的Generate Output Products和Create HDL Wrapper两大关键步骤,帮助新手理解其核心功能与操作要点。通过详细讲解文件生成类型、关键选项设置及常见问题解决方案,指导开发者正确使用这两个功能,避免设计流程中的常见错误,提高FPGA开发效率。

weixin_29207149的博客 310

从零到英雄:WSL2与Ubuntu22.04的终极性能调优指南

本文详细介绍了如何在Windows系统中通过WSL2与Ubuntu22.04进行性能调优,涵盖内核定制、GPU加速、网络优化等关键技巧,帮助开发者打造媲美原生Linux的高性能开发环境,特别适合AI训练和大数据处理等资源密集型任务。

weixin_29218509的博客 523

extended_text_field源码架构揭秘:它如何扩展并复刻Flutter官方TextField内部实现

**extended_text_field** 是一个 Flutter 开源组件库,它扩展了官方 `TextField`,让你在输入框里快速实现**行内图片、@提及某人、自定义背景文字**等特殊文本,还能定制选择工具栏和隐藏系统键盘。它的实现思路非常硬核:把 Flutter 官方 TextField 的内部源码复制进项目,再用继承的方式逐层增强。本文带你用大白话看懂这套源码架构是怎么搭起来的,适合

gitblog_01173的博客 377

无线Mesh组网全攻略:从原理、部署到调优与排障

对于布线困难的大户型、复式楼或园区,传统的无线中继往往面临带宽减半和链路不稳定的问题。无线Mesh网络通过多跳转发与自组织路由,让每个节点无需网线即可协作扩展覆盖,并依靠动态路径选择实现自愈。其核心技术涉及802.11s、HWMP路由协议,以及802.11k/v/r协同的无缝漫游,能有效提升终端切换体验。在实际部署中,设备选型、回程频段规划与布点位置直接决定网络质量。围绕无线Mesh的组网原理、设备选型、配置调优与故障排查,提供一套工程实践参考,帮助用户在复杂环境下构建稳定高效的无缝覆盖。

weixin_34098209的博客 271

Flutter TextField长按菜单汉化全攻略:从依赖配置到多语言适配

本文详细解析了Flutter应用中TextField长按菜单(如复制、粘贴)显示英文而非中文的问题根源,并提供了从添加flutter_localizations依赖、配置MaterialApp本地化代理到处理iOS平台Info.plist的完整汉化方案。文章还涵盖了单语言固定中文与多语言动态适配两种场景的最佳实践,帮助开发者彻底解决TextField本地化问题,提升应用用户体验。

gg901的博客 817

1.全基因组重测序数据分析介绍

二代测序原理及fastq数据解读、全基因组重测序数据分析内容

weixin_53682198的博客 1881

linux 基于debian/ubuntu AB系统适配(二)-updateEngine移植

其实A/B系统的原理很简单,大部分的工作都集中在uboot上,rootfs只是起到一个辅助的作用,但这个作用也就必不可少的。你会发现在这个其中并没有kernel的参与。

badbayyj的博客 1033

Flutter + OpenHarmony 用户输入框:TextField 与 InputDecoration 在多端表单中的交互设计

本文将深入剖析 `TextField` 与 `InputDecoration` 的核心机制,结合 **手机端最佳实践**,从交互逻辑、视觉反馈、性能安全三个维度,教你如何构建一套**高可用、高性能、高一致性**的表单输入方案,并提供一份可直接复用的工程级代码模板。

2401_88937325的博客 1286

YOLOv8 骨骼结构识别详细说明

YOLOv8骨骼结构识别是一种基于深度学习技术的医学影像分析方法,主要用于X光、CT等影像中的骨骼定位与识别。该系统具有多骨骼同步识别能力,可应用于手部、脊柱、骨盆等不同部位,并能精确定位骨骼关键点。技术实现包括数据预处理、模型训练、推理检测、关键点分析和批量处理五个核心模块,支持骨折检测、骨龄评估等临床应用。该系统需注意医学合规性,要求高质量标注数据,并针对骨骼影像特点进行特征工程优化,同时考虑不同设备的部署需求。

u010117029的博客 330
上一篇: Android Memory(二) -- 应用内存占用分析
下一篇: Android OpenCV基础(core模块)
网络安全-XG
博客等级 码龄5年 1万+粉丝 2752原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值