两种验证码输入方案的选型思路
在鸿蒙应用开发中,登录页或安全验证环节几乎离不开验证码输入框。虽然系统提供了标准的 TextInput 组件,但在实际业务中,我们往往需要更精细的控制:比如六个独立的方框、输入一位自动跳转下一位、高亮当前选中态,甚至完全屏蔽系统键盘而使用自定义数字盘。
针对这些需求,ArkUI 主要提供了两条技术路径:一是基于自定义键盘 + 隐藏 TextInput 的方案,适合对 UI 一致性要求极高、希望完全掌控键盘样式的场景;二是基于系统键盘 + inputMethod 框架的方案,利用原生输入法能力,开发成本更低且符合用户习惯。本文将深入拆解这两种实现逻辑,帮助你根据项目实际情况做出最优选择。
方案一:自定义键盘与焦点转移技巧
当你需要完全定制键盘样式(例如金融类 App 常见的安全键盘),或者希望避免系统键盘弹出时遮挡布局,自定义键盘方案是首选。其核心难点在于:如何让界面上展示的 Text 组件响应点击并拉起键盘,同时还能实时显示输入内容。
核心实现逻辑
这个方案的巧妙之处在于"移花接木"。我们在页面上放置一个透明的、隐藏的 TextInput 组件,并将其绑定自定义键盘。界面上看到的六个验证码框,实际上是由六个 Text 组件渲染的。
为了让点击 Text 能唤起键盘,我们需要利用 sendEventByKey 方法。当用户点击某个 Text 时,通过该方法将焦点事件转移给隐藏的 TextInput,从而触发软键盘弹出。
typescript
// 隐藏的真实输入框
TextInput({ controller: this.controller })
.width('100%')
.height(0)
.opacity(0)
.id('HiddenInput')
.customKeyboard(this.CustomKeyboardBuilder()) // 绑定自定义键盘
.onChange((value) => {
// 同步数据到展示层
this.codeTxt = value;
this.updateHighlight(value.length);
})
// 展示层的 Text 组件
Text(this.codeTxt[index])
.width(40)
.height(40)
.border(this.showMouse[index] ? activeBorder : normalBorder)
.onClick(() => {
// 关键步骤:将焦点转移给隐藏的 TextInput
sendEventByKey('HiddenInput', 10, '');
})
状态管理与自动跳转
为了实现"输入一位自动跳下一位"以及"当前位高亮"的效果,我们需要维护两个状态变量:
codeTxt:存储完整的验证码字符串。showMouse:一个布尔数组,用于标记哪一位处于激活(高亮)状态。
在 onChange 回调或 @Watch 监听中,根据 codeTxt 的长度动态更新 showMouse 数组。当长度小于最大位数时,将对应索引设为 true,其余为 false;当输满时,全部取消高亮。这种数据驱动视图的方式,能确保 UI 状态与输入内容严格同步。
方案二:系统键盘与输入法框架监听
如果项目没有特殊的键盘定制需求,直接使用系统原生键盘不仅能减少代码量,还能让用户获得熟悉的输入体验。但直接使用 TextInput 往往难以实现"六个独立框"的视觉效果,因此我们需要借助 inputMethod 框架来"曲线救国"。
绕过 TextInput 的直接监听
在这种方案下,页面上依然只放置六个 Text 组件用于展示,不再依赖 TextInput 进行数据绑定。取而代之的是,我们通过 inputMethod 模块直接控制输入法的显隐,并订阅其底层事件。
首先,需要在页面可见时绑定输入法控制器,并配置为数字键盘模式:
typescript
import inputMethod from '@ohos.inputMethod';
async attachAndListener() {
const textConfig: inputMethod.TextConfig = {
inputAttribute: {
textInputType: inputMethod.TextInputType.NUMBER,
enterKeyType: inputMethod.EnterKeyType.GO
}
};
// 绑定输入法
await this.inputController.attach(true, textConfig);
this.attachListener();
}
拦截插入与删除事件
绑定成功后,关键在于订阅 insertText 和 deleteLeft 事件。当用户在系统键盘上点击数字时,会触发 insertText 回调,我们将接收到的字符拼接到本地字符串变量中;当用户点击退格键时,deleteLeft 回调会被触发,此时截取字符串即可实现删除效果。
typescript
attachListener(): void {
// 监听插入文本
this.inputController.on('insertText', (text) => {
if (this.codeTxt.length >= 6) return;
this.codeTxt += text;
this.updateUI(); // 刷新界面高亮
});
// 监听删除操作
this.inputController.on('deleteLeft', (length) => {
this.codeTxt = this.codeTxt.substring(0, this.codeTxt.length - 1);
this.updateUI();
});
}
此外,为了提升体验,通常还会结合 onVisibleAreaChange 监听组件可见性。当验证码区域完全进入可视区时自动拉起键盘,离开时自动解绑,避免资源浪费。
方案对比与落地建议
两种方案各有优劣,选择时需权衡开发成本与用户体验。
自定义键盘方案 的优势在于极致的可控性。你可以完全定义键盘的布局、颜色和动画,彻底规避系统键盘弹起导致的页面重排问题,特别适合对安全性或品牌 UI 有严格要求的场景。但其缺点也很明显:需要手动处理焦点转移、自行绘制键盘 UI,且无法享受系统输入法自带的纠错、语音输入等高级功能,开发工作量较大。
系统键盘方案 则胜在轻量与原生体验 。利用 inputMethod 框架,我们既保留了原生键盘的流畅度,又实现了自定义的 UI 展示。代码逻辑相对清晰,维护成本低,且天然支持多语言输入切换。唯一的局限是必须依赖系统键盘的存在,若系统键盘本身存在兼容性问题,可能会影响表现。
在实际落地中,如果是普通的 C 端应用登录页,推荐优先采用系统键盘方案 ,快速上线且体验稳定;若是银行、支付等对安全键盘有强制规范的场景,则自定义键盘方案是不二之选。无论哪种方式,核心都在于理清数据流与视图的映射关系,利用 ArkUI 的状态管理机制,让验证码输入过程既流畅又美观。