鸿蒙新特性——TextInput 文本输入组件详解 一、引言在移动端应用中文本输入是最基础也是最频繁的用户交互方式。登录时需要输入用户名和密码注册时需要填写邮箱和手机号搜索时需要输入关键词评论时需要输入内容——几乎每个页面的核心交互都离不开文本输入框。移动端的文本输入远不止敲几个字那么简单。不同类型的输入内容需要不同的键盘布局密码需要遮蔽显示并提供显隐切换手机号需要数字键盘并限制位数邮箱需要符号快捷输入。在桌面端键盘是外设输入框只是一个接受字符串的矩形但在移动端输入框需要和软键盘紧密配合——键盘类型、回车键行为、聚焦时的滚动避让、密码的显示/隐藏切换——这些都是在桌面端不存在的交互维度。传统实现一个完整的注册表单需要为每个字段手动配置输入框 占位符 键盘类型 输入校验 字符计数 密码显隐图标。即便用 ArkUI 的声明式语法如果不了解 TextInput 的全部 API开发者可能会走弯路——例如自己画一个眼睛图标来实现密码切换而不使用内置的showPasswordIcon。HarmonyOS 提供了TextInput组件——一个功能完备的单行文本输入框。它内置了对十几种输入类型文本、密码、新密码、邮箱、数字、小数、电话号码、URL、用户名、验证码等的支持集成了密码显隐切换、字符计数、占位符样式、回车键类型等常用功能。开发者只需要声明type和绑定onChange回调TextInput 自动处理键盘切换、密码遮蔽、输入过滤等逻辑。本文通过一个用户注册表单Demo 深入讲解 TextInput 组件的核心用法如何配置不同的输入类型如何使用密码显隐切换如何实现字符计数如何进行表单校验如何通过onChange实时监听输入内容阅读完本文你将能够使用InputType枚举配置正确的键盘类型Normal/Password/Email/PhoneNumber 等使用showPasswordIcon实现密码一键显隐切换使用maxLengthshowCounter实现字符限制与实时计数使用placeholderplaceholderColorplaceholderFont定制占位符通过onChange回调实时获取输入内容并实现联动校验在表单页面中组合多个 TextInput 构建完整的输入流程二、TextInput 组件 API 总览2.1 构造函数TextInput(value?:TextInputOptions)TextInput 的构造函数接收一个可选配置对象定义初始值和占位符declareinterfaceTextInputOptions{placeholder?:ResourceStr;// 占位符文本输入框为空时显示text?:ResourceStr;// 输入框的当前值controller?:TextInputController;// 控制器用于程序化操作光标}最简用法——仅需占位符TextInput({placeholder:请输入用户名})带初始值的用法TextInput({placeholder:请输入用户名,text:默认名称})2.2 InputType —— 输入类型枚举TextInput 的核心能力之一是通过type()方法设置输入类型不同的类型会触发不同的系统键盘布局和输入行为枚举值键盘行为适用场景InputType.Normal标准文本键盘用户名、昵称、通用文本InputType.Password密码键盘遮蔽字符 眼睛图标登录密码InputType.NEW_PASSWORD新密码键盘可自动生成强密码注册密码InputType.NUMBER_PASSWORD纯数字密码键盘支付密码、PIN 码InputType.Email邮箱键盘含 快捷键邮箱地址InputType.Number纯数字键盘整数输入InputType.NUMBER_DECIMAL数字 小数点键盘金额、体重等小数InputType.PhoneNumber电话号码键盘手机号、座机号InputType.URLURL 输入键盘网址输入InputType.USER_NAME用户名键盘与密码保险箱联动登录用户名的自动填充InputType.ONE_TIME_CODE一次性验证码键盘短信验证码关键规律文本类Normal/Email/URL全键盘布局数字类Number/NUMBER_DECIMAL/PhoneNumber数字键盘布局密码类Password/NEW_PASSWORD/NUMBER_PASSWORD遮蔽字符 眼睛图标辅助类USER_NAME/ONE_TIME_CODE与系统自动填充服务联动2.3 核心方法一览TextInput 的方法分为几类输入控制、样式定制、回调事件。输入控制方法方法用途示例type(value: InputType)设置输入类型.type(InputType.Password)maxLength(value: number)最大字符数.maxLength(11)showCounter(value: boolean)显示字符计数器.showCounter(true)showPasswordIcon(value: boolean)显示密码显隐切换图标.showPasswordIcon(true)enterKeyType(value: EnterKeyType)设置软键盘回车键样式.enterKeyType(EnterKeyType.Done)样式定制方法方法用途placeholderColor(color)占位符文字颜色placeholderFont(font)占位符字体大小、粗细等fontSize(size)输入文本字体大小fontColor(color)输入文本颜色fontWeight(weight)输入文本粗细caretColor(color)光标颜色backgroundColor(color)输入框背景色borderRadius(radius)输入框圆角回调事件方法方法触发时机回调参数onChange(callback)输入内容变化时(value: string) voidonSubmit(callback)按下回车键时(enterKey: EnterKeyType) voidonEditChange(callback)编辑状态变化时获得/失去焦点(isEditing: boolean) voidonCopy(callback)复制文本时(value: string) voidonCut(callback)剪切文本时(value: string) voidonPaste(callback)粘贴文本时(value: string) void2.4 基本用法模式Stateusername:string;TextInput({placeholder:请输入用户名,text:this.username}).type(InputType.Normal).maxLength(20).showCounter(true).fontSize(14).placeholderColor(#BBBBCC).backgroundColor(#F8F9FA).borderRadius(8).height(44).onChange((value:string){this.usernamevalue;})TextInput 的用法模式核心构造函数设置placeholder和text绑定到 Statetype()确定键盘类型样式链配置外观onChange回调中更新 State实现双向绑定2.5 密码字段的特殊处理当type为InputType.Password或InputType.NEW_PASSWORD时TextInput 的行为与普通输入框不同输入的字符默认被圆点遮蔽●可以通过showPasswordIcon(true)启用内置的眼睛图标用户点击眼睛图标时密码临时明文显示API 20 起NEW_PASSWORD还可以配合系统的密码自动生成功能注意showPasswordIcon仅在Password/NEW_PASSWORD/NUMBER_PASSWORD类型下生效。如果使用Normal类型并期望有眼睛图标需要自己实现不推荐——直接用密码类型即可。2.6 onChange 与 $$ 双向绑定onChange是 TextInput 最常用的回调在用户每次输入时触发。标准模式是在回调中将新值赋给 State 变量TextInput({text:this.username}).onChange((value:string){this.usernamevalue;})ArKUI 也支持$$语法实现自动双向绑定API 10但显式onChange更灵活——你可以在回调中做额外的处理如过滤特殊字符、实时校验等。三、Demo 设计用户注册表单3.1 功能概述Demo 是一个用户注册表单页面模拟真实 App 注册流程5 个输入字段用户名Normal、密码Password、确认密码Password、邮箱Email、手机号PhoneNumber实时字符计数用户名和手机号字段显示字符计数器密码显隐切换密码和确认密码字段支持一键切换明文/密文表单校验提交时验证所有字段长度、格式、一致性错误提示校验不通过时以红色卡片展示所有错误成功反馈校验通过后展示注册信息已提交卡片列出提交的数据重置功能一键清空所有字段和错误状态所有 5 个 TextInput 使用不同的InputType展示键盘类型的多样性。3.2 表单字段与 InputType 映射字段InputType特殊配置校验规则用户名NormalmaxLength20, showCounter长度 4密码PasswordshowPasswordIcon长度 6确认密码PasswordshowPasswordIcon与密码一致邮箱Email-邮箱格式手机号PhoneNumbermaxLength11, showCounter长度 11每个字段的 InputType 都不同体现了 TextInput 对不同输入场景的适配。3.3 字段定义与状态管理Stateusername:string;Statepassword:string;StateconfirmPassword:string;Stateemail:string;Statephone:string;Stateerrors:string[][];Statesubmitted:booleanfalse;七个 State 变量分别管理五个输入值、一个错误列表和一个提交状态。当onChange触发时对应的 State 更新当提交按钮点击时validate()方法填充错误列表或设置submitted true。3.4 字段布局每个字段采用统一的垂直布局——标签行 输入框// Username fieldColumn(){Row(){Text(用户名).fontSize(14).fontColor(#1a1a2e).fontWeight(FontWeight.Medium)Text( *).fontSize(14).fontColor(#FF4D4F)}.margin({bottom:6})TextInput({placeholder:请输入用户名4-20位,text:this.username}).type(InputType.Normal).maxLength(20).showCounter(true).backgroundColor(#F8F9FA).borderRadius(8).height(44).width(100%).fontSize(14).placeholderColor(#BBBBCC).onChange((value:string){this.usernamevalue;})}.width(100%).margin({bottom:Spacing.LG})标签用Row组合——字段名 红色星号必填标识输入框统一配置为 44 高度、8 圆角、浅灰背景。密码字段的关键差异在于type和showPasswordIconTextInput({placeholder:请输入密码6-20位,text:this.password}).type(InputType.Password).showPasswordIcon(true)// ... 样式配置.onChange((value:string){this.passwordvalue;})showPasswordIcon(true)会在输入框右侧显示一个眼睛图标。用户点击图标时密码从圆点变为明文再次点击恢复遮蔽。整个交互由 TextInput 内置实现无需额外的状态管理。手机号字段使用InputType.PhoneNumber自动切换到数字电话键盘布局TextInput({placeholder:请输入11位手机号码,text:this.phone}).type(InputType.PhoneNumber).maxLength(11).showCounter(true)// ... 样式配置InputType.PhoneNumber不仅提供数字键盘还对输入内容做了限制——只接受数字和少量特殊字符、-、空格等。3.5 表单校验逻辑validate():boolean{this.errors[];if(this.username.trim().length4){this.errors.push(用户名至少需要4个字符);}if(this.password.length6){this.errors.push(密码至少需要6个字符);}if(this.password!this.confirmPassword){this.errors.push(两次输入的密码不一致);}constemailRegex/^[^\s][^\s]\.[^\s]$/;if(!emailRegex.test(this.email.trim())){this.errors.push(请输入有效的邮箱地址);}if(this.phone.trim().length!11){this.errors.push(手机号必须为11位数字);}returnthis.errors.length0;}校验逻辑依次检查五项规则每项不通过就向errors数组推入一条错误信息。所有检查完成后errors 为空表示校验通过。3.6 错误提示与成功反馈校验不通过时errors数组非空页面时显一个红色边框的提示卡片if(this.errors.length0){Column(){ForEach(this.errors,(err:string,idx:number){Row(){Text(⚠️).fontSize(12).margin({right:6})Text(err).fontSize(12).fontColor(#FF4D4F)}.width(100%).padding({top:3,bottom:3})})}.width(100%).padding(Spacing.LG).backgroundColor(#FFF2F0).borderRadius(BorderRadius.LG).border({width:1,color:#FFCCC7})}所有错误在同一个卡片中列出用户可以一次性看到哪些字段需要修正——而不是每次只弹出一个错误提示。校验通过后submitted变为 true显示提交成功卡片if(this.submitted){Column(){Text(✅ 注册信息已提交).fontSize(15).fontColor(#52C41A).fontWeight(FontWeight.Bold).margin({bottom:Spacing.MD})Column(){this.dataRow(用户名,this.username)Divider().strokeWidth(0.5).color(#E8E8ED)this.dataRow(邮箱,this.email)Divider().strokeWidth(0.5).color(#E8E8ED)this.dataRow(手机号,this.phone)}}}注意成功卡片只展示非敏感信息用户名、邮箱、手机号密码不在其中——这是实际应用中需要注意的安全细节。3.7 页面结构┌──────────────────────────────────────────┐ │ 用户注册深色标题栏 │ ├──────────────────────────────────────────┤ │ TextInput 组件说明卡片 │ ├──────────────────────────────────────────┤ │ ┌ 填写注册信息 ──────────────────────┐ │ │ │ 用户名 * │ │ │ │ [请输入用户名4-20位] 0/20 │ │ │ │ │ │ │ │ 密码 * │ │ │ │ [请输入密码6-20位] │ │ │ │ │ │ │ │ 确认密码 * │ │ │ │ [请再次输入密码] │ │ │ │ │ │ │ │ 邮箱 * │ │ │ │ [请输入邮箱地址] │ │ │ │ │ │ │ │ 手机号 * │ │ │ │ [请输入11位手机号码] 0/11 │ │ │ └─────────────────────────────────────┘ │ ├──────────────────────────────────────────┤ │ [重置] [提交注册] │ ├──────────────────────────────────────────┤ │ 错误提示卡片 — 校验不通过时显示 │ │ 成功卡片 — 校验通过后显示 │ └──────────────────────────────────────────┘四、TextInput 组件的最佳实践4.1 选择合适的 InputTypeInputType 不仅影响系统键盘布局还影响输入行为和安全特性密码字段始终使用InputType.Password或InputType.NEW_PASSWORD。不要用Normal 自定义遮蔽逻辑——Password 类型内置了密码保险箱联动、防止截屏、剪贴板管理等安全机制。手机号/验证码使用InputType.PhoneNumber或InputType.Number用户看到的是数字键盘减少输入错误。邮箱使用InputType.Email键盘提供 和 . 的快捷输入。金额/小数使用InputType.NUMBER_DECIMAL键盘提供数字和小数点且限制只能输入一个点号。选错 InputType 的代价不是编译错误而是用户体验下降——用户打开注册页看到全键盘而非常数字键盘错误率会明显上升。4.2 onChange 中的实时校验 vs 提交时校验TextInput 的onChange在每次输入时触发。有两种校验策略实时校验在 onChange 中校验.onChange((value:string){this.usernamevalue;if(value.length20){// 实时提示}})提交时校验在提交按钮点击时校验.onChange((value:string){this.usernamevalue;// 仅更新状态不校验})Button(提交).onClick((){if(this.validate()){/* ... */}})推荐使用提交时校验。原因有三实时校验会打断用户输入——还没输完就弹出红色提示体验很差某些校验规则在输入过程中无法判断——比如确认密码一致在用户还没输入完确认密码时必然不一致减少不必要的 UI 刷新——onChange 高频触发在其中做校验逻辑会增加组件刷新频率唯一的例外是字符计数showCounter——它是非侵入性的提示不打断用户适合实时显示。4.3 maxLength showCounter 的协同maxLength限制最大字符数showCounter显示当前已输入字符数。两者配合使用时计数器会自动显示为已输入/最大格式如5/20TextInput({placeholder:请输入用户名,text:this.username}).type(InputType.Normal).maxLength(20).showCounter(true)注意事项maxLength限制的是字符数不是字节数中文和英文各算 1 个字符达到 maxLength 后软键盘不接受新字符但粘贴操作可能被截断showCounter的显示位置在输入框底部右侧占用少量垂直空间4.4 在 Scroll 中嵌入 TextInput移动端表单通常很长多字段 按钮 提示信息需要放在 Scroll 中滚动。但 TextInput 在 Scroll 中有个常见问题聚焦时软键盘弹起可能遮挡输入框。HarmonyOS 的 Scroll 组件默认会自动处理键盘避让——当输入框聚焦时页面自动上移确保输入框可见。但如果表单很短不到一屏可能不需要 Scroll如果表单很长Scroll 配合自动避让是标准方案。Scroll(){Column(){// 多个 TextInput 字段}}.layoutWeight(1)Scroll 使用layoutWeight(1)占据标题栏下方的全部空间确保内容超出屏幕时可以滚动。4.5 showPasswordIcon 的局限showPasswordIcon(true)仅在InputType.Password/NEW_PASSWORD/NUMBER_PASSWORD下有效。如果希望在普通输入框中添加眼睛图标例如搜索框中的清除按钮需要在 TextInput 外部自定义图标——TextInput 本身不提供自定义尾部图标的 API。另外showPasswordIcon使用的是系统内置的眼睛图标。如果设计稿要求自定义图标样式需要设置showPasswordIcon(false)或不设置然后在 TextInput 外部自己实现切换逻辑——不过这会失去 Password 类型的部分安全特性。4.6 TextInput 与 TextArea 的选择TextInput 是单行输入框TextArea 是多行文本框。选择规则特性TextInputTextArea行数1 行固定多行可滚动回车键触发 onSubmit换行适用场景用户名、密码、手机号、搜索评论、简介、反馈、备注高度固定~44vp可自定义选择规则单行、固定高度、回车提交 → TextInput。多行、内容可能较长、回车换行 → TextArea。五、完整代码结构TextInputPage (~300 行) ├── 状态变量 │ ├── State username/password/confirmPassword/email/phone — 5 个输入值 │ ├── State errors: string[] — 校验错误列表 │ └── State submitted: boolean — 提交状态 ├── 方法 │ ├── validate(): boolean — 表单校验逻辑 │ ├── submitForm() — 提交处理 │ └── resetForm() — 重置所有字段 ├── 视图 │ ├── 标题栏 — 用户注册 │ ├── 说明卡片 — TextInput 组件介绍 │ ├── 表单卡片5 个字段每个独立 Column 布局 │ ├── 错误提示卡片条件渲染 │ ├── 按钮行重置 提交 │ └── 成功反馈卡片条件渲染 └── Builder └── dataRow() — 数据展示行六、总结本文通过一个用户注册表单Demo 深入讲解了 HarmonyOS 中的TextInput 单行文本输入框组件。TextInput 将文本输入的核心交互——键盘类型切换、密码遮蔽、字符计数、占位符、输入校验——封装为一个统一的声明式组件通过type()切换十几种输入模式通过showPasswordIcon一键启用密码显隐通过onChange实现实时数据绑定。核心要点回顾InputType 是 TextInput 的核心不同 InputType 决定键盘布局和输入行为。密码类自动遮蔽数字类自动切换数字键盘邮箱类提供 快捷键。正确选择 InputType 是良好用户体验的基础。密码字段推荐用 Password 类型不要用 Normal 自定义遮蔽。Password 类型内置了安全机制截屏防护、密码保险箱联动且通过showPasswordIcon(true)即可启用显隐切换。maxLength showCounter 是字符限制的标准方案两者配合自动显示已输入/最大格式无需手动计算和渲染计数器。onChange 中更新状态提交时校验不要在 onChange 中做校验打断输入而是仅在 onChange 中更新 State在提交按钮的 onClick 中统一校验。TextInput 是表单页面的基础组件配合不同的 InputType、校验逻辑和提交反馈TextInput 可以构建从简单搜索框到复杂注册表单的各种输入场景。TextInput 的 API 方法多达 100从基础样式到高级功能如 customKeyboard、autofill、内容过滤但 80% 的场景只需要 type placeholder onChange 基本样式配置。本文覆盖的是每个使用 TextInput 的开发者都需要掌握的核心模式——掌握这些后再根据具体需求查阅高级 API 即可。七、扩展思考TextInput 覆盖了基础的文本输入需求但实际项目中的输入框场景更加丰富TextArea 多行输入当用户需要输入长文本评论、简介、反馈时单行的 TextInput 不够用。TextArea 提供了多行输入能力但失去了 InputType 的类型支持——大部分高级输入类型Password、Email 等仅在单行场景有意义。与 TextPicker/Select 的配合表单页面中不是所有字段都需要自由输入。手机验证码适合 TextInput 倒计时按钮的组合性别/地区等枚举选择适合 Select 或 TextPicker出生日期适合 DatePicker。在一个完整的注册表单中TextInput 和这些选择类组件通常混合使用。内容过滤与输入限制maxLength限制字符数但如果需要限制输入字符类型例如只能输入中文、禁止特殊字符需要使用inputFilter方法配合正则表达式。更复杂的内容过滤如敏感词过滤需要在 onChange 中自行处理。与后端校验的配合前端校验格式、长度、必填是用户体验的第一层但最终校验在后端用户名是否已注册、验证码是否正确。在onSubmit回调中触发后端校验校验结果通过 State 驱动 UI 更新——这与前端校验的渲染模式一致。密码强度指示器注册场景中通常需要告知用户密码强度。可以在 onChange 中实时分析密码复杂度是否含数字、大小写字母、特殊字符并在输入框下方渲染强度指示条——这是 TextInput 自定义 UI 的经典组合。理解 TextInput 的定位——单行、类型驱动、轻量级的文本输入组件——是正确使用它的关键。它不是富文本编辑器那是 RichEditor 的职责不是多行文本域那是 TextArea 的职责而正是这种专注让它成为了移动端表单中最基础、最高频、最灵活的输入交互方案。通过本文的 Demo——用户注册表单页面你将 5 个不同 InputType 的 TextInput 组件组织在完整的注册流程中体验了从输入、校验到提交反馈的标准模式。这个页面可以作为任何 App 注册功能的起点模板。