HarmonyOS Next 系列之验证码输入组件实现(二)

发布时间:2026/8/7 18:02:10
HarmonyOS Next 系列之验证码输入组件实现(二)
系列文章目录HarmonyOS Next 系列之省市区弹窗选择器实现一HarmonyOS Next 系列之验证码输入组件实现二HarmonyOS Next 系列之底部标签栏TabBar实现三HarmonyOS Next 系列之HTTP请求封装和Token持久化存储四HarmonyOS Next 系列之从手机选择图片或拍照上传功能实现五HarmonyOS Next 系列之可移动悬浮按钮实现六HarmonyOS Next 系列之沉浸式状态实现的多种方式七HarmonyOS Next系列之Echarts图表组件折线图、柱状图、饼图等)实现八HarmonyOS Next系列之地图组件Map Kit使用九HarmonyOS Next系列之半圆环进度条实现十HarmonyOS Next 系列之列表下拉刷新和触底加载更多数据实现十一HarmonyOS Next系列之实现一个左右露出中间大两边小带缩放动画的轮播图十二文章目录系列文章目录前言一、实现原理二、代码实现1.定义参数和变量配置2、自绘控件输入法事件回调设置和事件解绑3、验证码输入框布局和输入法绑定与解绑完整代码页面调用前言HarmonyOS Next基于API11 实现一个验证码输入组件VerifyCodeInput不可复制粘贴输入验证码无光标自动定位到下一格删除自动定位到前一格验证码个数可配置。一、实现原理为了解决输入或删除自动移格通过Text组件来显示验证码而非TextInput,键盘输入通过inputMethod.InputMethodController 自绘控件绑定输入法形式进行输入内容监听最后通过组件本身onVisibleAreaChange事件判断页面是隐藏跳转下一页或者显示返回动态控制键盘弹出和隐藏二、代码实现VerifyCodeInput.ets1.定义参数和变量配置Componentexportdefaultstruct VerifyCodeInput{//单个输入框高Prop iheight:number|string48//单个输入框宽Prop iwidth:number|string48//验证码字体大小Prop fontsize:number|string20fp//验证码框个数Prop count:number6//输入法客户端实例privateinputController:inputMethod.InputMethodControllerinputMethod.getController();//自绘编辑框配置privatetextConfig:inputMethod.TextConfig{inputAttribute:{textInputType:inputMethod.TextInputType.NUMBER,//只能输入数字enterKeyType:inputMethod.EnterKeyType.GO},};//用户输入的验证码Link inputCode:string//验证码输入框个数数组State countArr:number[]newArray(this.count??6).fill( )//count个空元素数组//是否第一次加载privateisFirst:booleantrue说明首先定义了一些组件参数如单个输入框宽高、字体大小、输入框个数等和新建输入法实例inputController并设置只能输入数字。2、自绘控件输入法事件回调设置和事件解绑//自绘控件绑定输入法 params isFocus:是否聚焦拉起键盘asynconAttachInput(isFocus?:boolean){try{//绑定成功默认拉起键盘awaitthis.inputController.attach(isFocus??true,this.textConfig);}catch(e){console.log(JSON.stringify(e))}}//自绘控件解绑输入法asynconDetachInput(){try{awaitthis.inputController.detach()}catch(e){console.log(JSON.stringify(e))}}//绑定输入法输入和删除事件onInputEvent(){//输入数字this.inputController.on(insertText,(text:string){if(textthis.inputCode.lengththis.count!isNaN(Number(text))){this.inputCodetext;}})//删除数字this.inputController.on(deleteLeft,(length:number){this.inputCodethis.inputCode.substring(0,this.inputCode.length-1);})}//解除输入法事件offInputEvent(){this.inputController.off(insertText);this.inputController.off(deleteLeft);}//组件销毁解除所有绑定aboutToDisappear(){this.offInputEvent()this.onDetachInput()}说明此步骤主要是输入法初始化配置和定义输入事件输入和删除回调设置以及解绑以上所有事件3、验证码输入框布局和输入法绑定与解绑build(){Column(){Row(){ForEach(this.countArr,(item:string,index:number){Text(this.inputCode[index]).width(this.iwidth).height(this.iheight).borderRadius(8).backgroundColor(#ECF1F7).fontSize(this.fontsize).fontWeight(500).textAlign(TextAlign.Center).margin({left:index0?0:5,right:index5?0:5}).flexGrow(1).onClick((){//点击控件重新绑定弹出键盘this.onAttachInput()})},(item:string,index:number)index.toString())}.justifyContent(FlexAlign.SpaceBetween).onVisibleAreaChange([0.0,1.0],async(isVisible:boolean,currentRatio:number){if(isVisiblecurrentRatio1.0){//页面显示//延迟200ms兼容绑定失效问题setTimeout(async(){try{//绑定输入法和设置聚焦状态弹出键盘awaitthis.onAttachInput(true)}catch(e){}if(this.isFirst){//首次加载//绑定输入事件this.onInputEvent()this.isFirstfalse}},200)}if(!isVisiblecurrentRatio0.0){//页面隐藏//隐藏键盘this.onAttachInput(false)}})}.width(100%)}说明绘制count默认6个个验证码输入框首次加载绑定键盘输入事件并通过onVisibleAreaChange事件来辅助判断页面是否跳转或返回重新显示页面页面跳转时候隐藏键盘页面重现时恢复弹出键盘这边有个坑在页面返回时候需要延迟绑定输入法弹否则弹出键盘会有异常。入参有iheight组件高 number|stringiwidth:组件宽 number|stringcount 验证码个数 number 默认值6value 用户输入的验证码 string 双向绑定值完整代码目录VerifyCodeInput.etsimport{inputMethod}fromkit.IMEKit;Componentexportdefaultstruct VerifyCodeInput{//单个输入框高Prop iheight:number|string48//单个输入框宽Prop iwidth:number|string48//验证码字体大小Prop fontsize:number|string20fp//验证码框个数Prop count:number6//输入法客户端实例privateinputController:inputMethod.InputMethodControllerinputMethod.getController();//自绘编辑框配置privatetextConfig:inputMethod.TextConfig{inputAttribute:{textInputType:inputMethod.TextInputType.NUMBER,//只能输入数字enterKeyType:inputMethod.EnterKeyType.GO},};//用户输入的验证码Link inputCode:string//验证码输入框个数数组State countArr:number[]newArray(this.count??6).fill( )//count个空元素数组//是否第一次加载privateisFirst:booleantrue//自绘控件绑定输入法 params isFocus:是否聚焦拉起键盘asynconAttachInput(isFocus?:boolean){try{//绑定成功默认拉起键盘awaitthis.inputController.attach(isFocus??true,this.textConfig);}catch(e){console.log(JSON.stringify(e))}}//自绘控件解绑输入法asynconDetachInput(){try{awaitthis.inputController.detach()}catch(e){console.log(JSON.stringify(e))}}//绑定输入法输入和删除事件onInputEvent(){//输入数字this.inputController.on(insertText,(text:string){if(textthis.inputCode.lengththis.count!isNaN(Number(text))){this.inputCodetext;}})//删除数字this.inputController.on(deleteLeft,(length:number){this.inputCodethis.inputCode.substring(0,this.inputCode.length-1);})}//解除输入法事件offInputEvent(){this.inputController.off(insertText);this.inputController.off(deleteLeft);}//组件销毁解除所有绑定aboutToDisappear(){this.offInputEvent()this.onDetachInput()}build(){Column(){Row(){ForEach(this.countArr,(item:string,index:number){Text(this.inputCode[index]).width(this.iwidth).height(this.iheight).borderRadius(8).backgroundColor(#ECF1F7).fontSize(this.fontsize).fontWeight(500).textAlign(TextAlign.Center).margin({left:index0?0:5,right:index5?0:5}).flexGrow(1).onClick((){//点击控件重新绑定弹出键盘this.onAttachInput()})},(item:string,index:number)index.toString())}.justifyContent(FlexAlign.SpaceBetween).onVisibleAreaChange([0.0,1.0],async(isVisible:boolean,currentRatio:number){if(isVisiblecurrentRatio1.0){//页面显示//延迟200ms兼容绑定失效问题setTimeout(async(){try{//绑定输入法和设置聚焦状态弹出键盘awaitthis.onAttachInput(true)}catch(e){}if(this.isFirst){//首次加载//绑定输入事件this.onInputEvent()this.isFirstfalse}},200)}if(!isVisiblecurrentRatio0.0){//页面隐藏//隐藏键盘this.onAttachInput(false)}})}.width(100%)}}页面调用Index.etsimportVerifyCodeInputfrom../components/VerifyCodeInput/VerifyCodeInputEntry Component struct Index{//输入的验证码,双向绑定State value:stringbuild(){Navigation(){Column(){VerifyCodeInput({inputCode:this.value})}.width(100%)}.title(验证码输入).titleMode(NavigationTitleMode.Mini)}}效果