鸿蒙开发(一)自定义验证码输入框
·
在移动端应用中,验证码输入是非常常见的交互场景。默认的 TextInput 组件虽然可以完成输入,但在用户体验上存在一些不足:
- 无法直观显示固定长度的验证码
- 当前输入位焦点不明显
- 无法灵活自定义样式
本文将结合鸿蒙 ArkUI(JavaScript/TypeScript) 的能力,分享我自定义验证码输入框的实现方法,支持:
- 指定位数验证码
- 当前输入位高亮
- 输入完成回调
- 支持重置功能
一、核心思路
实现自定义验证码输入框的关键思路如下:
- 数据驱动:
每一位验证码对应一个对象,保存内容和是否被选中状态,通过@ObservedV2和@Local管理状态变化。 - UI 渲染:
-
- 使用
Row横向排列每个验证码格子 Text显示每位内容- 选中格子高亮显示
- 使用
- 输入逻辑:
-
- 使用一个透明的
TextInput接收所有输入 - 输入变化时,更新每个格子内容
- 删除时自动回退
- 完成输入触发回调
- 使用一个透明的
- 扩展性:
-
- 支持重置输入框
- 可自定义颜色、格子大小和间距
二、数据模型
首先定义每位验证码的数据对象:
@ObservedV2
export class InputContentObj {
id: string = "";
@Trace content: string = "";
@Trace isSelected: boolean = false;
constructor(id: string, content: string) {
this.id = id;
this.content = content;
this.isSelected = false;
}
}
id:格子的唯一标识content:当前格子内容isSelected:是否高亮显示
通过数组 InputContentObj[] 管理整个验证码:
@Local inputCode: InputContentObj[] = [];
三、组件实现
1. 参数和状态
@ComponentV2
export struct ComCodeInputView {
@Local digit: number = 4; // 验证码位数
@Local inputCode: InputContentObj[] = []
textWidth: number = 40
textInterval: number = 10
@Local selectedColor: ResourceColor = ComColors.color_product
@Local defaultColor: ResourceColor = ComColors.color_cccccc
@Param @Require onCodeChange?: VerifyCodeChangeCallback
@Param resetFlag: number = 0
@Local inputViewContent: string = ""
digit:验证码位数textWidth/textInterval:格子大小与间距selectedColor/defaultColor:选中和默认颜色onCodeChange:输入完成回调resetFlag:重置标志inputViewContent:绑定到隐藏的TextInput
2. 初始化和重置
initCode() {
this.inputCode = [];
for (let i = 0; i < this.digit; i++) {
const inputContentObj = new InputContentObj(i.toString(), "");
inputContentObj.isSelected = (i == 0);
this.inputCode.push(inputContentObj);
}
}
@Monitor("resetFlag")
reset() {
for (let i = 0; i < this.digit; i++) {
this.inputCode[i].content = "";
this.inputCode[i].isSelected = (i == 0);
}
setTimeout(() => {
this.inputViewContent = "";
}, 500);
}
initCode:组件显示前初始化数组reset:重置内容并设置首位高亮
3. 渲染 UI
build() {
Stack({ alignContent: Alignment.Center }) {
Row({ space: this.textInterval }) {
ForEach(this.inputCode, (value: InputContentObj, index: number) => {
Text(value.content)
.width(this.textWidth)
.height(this.textWidth)
.textAlign(TextAlign.Center)
.border({
width: 1,
color: value.isSelected ? this.selectedColor : this.defaultColor,
radius: 8
})
.key(value.id);
}, (item: InputContentObj) => item.id)
}
TextInput({ text: this.inputViewContent })
.width(this.digit * (this.textWidth + this.textInterval))
.maxLength(this.digit)
.key(this.resetFlag.toString())
.opacity(0)
.id("ComCodeInputView")
.onChange((value: string) => this.handleInputChange(value))
.onAppear(() => focusControl.requestFocus("ComCodeInputView"));
}.width(Percent.percent_100)
}
- 每个格子通过
Text渲染 - 透明
TextInput捕获用户输入 onAppear自动聚焦
4. 输入逻辑
handleInputChange(value: string) {
let codeInput = value.split('');
const cacheInfo: string[] = [];
for (let i = 0; i < this.digit; i++) {
cacheInfo[i] = codeInput[i] || "";
this.inputCode[i].content = cacheInfo[i];
}
const inputResult = this.inputCode.map(item => item.content).join('');
const inputResultLength = inputResult.length;
for (let i = 0; i < this.digit; i++) {
this.inputCode[i].isSelected = (i == inputResultLength);
}
this.onCodeChange?.(inputResult, inputResultLength === this.digit);
}
- 自动更新每个格子
- 删除时自动回退
- 判断输入完成并回调
四、效果展示
- 当前输入格子高亮
- 删除自动回退
- 完整输入触发回调
可视化效果示意图:

外部调用:

五、优化与经验
- 性能
避免大量@Local频繁变动,可考虑整个数组替换。 - 扩展性
-
- 可自定义粘贴支持
- 自定义格子样式、颜色、大小
- 兼容性
-
- 注意不同屏幕尺寸适配
- 数字/字母混合输入支持
六、注意事项
在实现控件的过程中,需要特别注意,关于同一个控件由于多个状态值控制导致同一时刻多次刷新,最终导致状态错乱的问题,规避手段如下:
(1)延时部分刷新——本控件目前是这样
(2)刷新对象抽离成一个
七、总结
通过以上方法,我们可以在鸿蒙中快速实现一个 自定义验证码输入框,相比默认组件,用户体验更加直观、友好,并且易于扩展和定制。
更多推荐



所有评论(0)