赞
踩
HarmonyOS Next 系列之省市区弹窗选择器实现(一)
HarmonyOS Next 系列之验证码输入组件实现(二)
HarmonyOS Next(基于API11) 实现一个验证码输入组件(VerifyCodeInput),不可复制粘贴,输入验证码无光标自动定位到下一格,删除自动定位到前一格,验证码个数可配置。
为了解决输入或删除自动移格通过Text组件来显示验证码而非TextInput,键盘输入通过inputMethod.InputMethodController 自绘控件绑定输入法形式进行输入内容监听,最后通过组件本身
onVisibleAreaChange事件判断页面是隐藏(跳转下一页)或者显示(返回)动态控制键盘弹出和隐藏
VerifyCodeInput.ets
@Component
export default struct VerifyCodeInput {
//单个输入框高
@Prop iheight:number|string=48
//单个输入框宽
@Prop iwidth:number|string=48
//验证码字体大小
@Prop fontsize:number|string='20fp'
//验证码框个数
@Prop count:number=6
//输入法客户端实例
private inputController: inputMethod.InputMethodController = inputMethod.getController();
//自绘编辑框配置
private textConfig: inputMethod.TextConfig = {
inputAttribute: {
textInputType: inputMethod.TextInputType.NUMBER, //只能输入数字
enterKeyType: inputMethod.EnterKeyType.GO
},
};
//用户输入的验证码
@Link inputCode: string
//验证码输入框个数数组
@State countArr: number[] = new Array(this.count??6).fill(' ') //count个空元素数组
//是否第一次加载
private isFirst:boolean=true
说明:首先定义了一些组件参数如单个输入框宽高、字体大小、输入框个数等和新建输入法实例inputController并设置只能输入数字。
//自绘控件绑定输入法 @params isFocus:是否聚焦拉起键盘
async onAttachInput(isFocus?:boolean) {
try {
//绑定成功默认拉起键盘
await this.inputController.attach(isFocus??true, this.textConfig);
}
catch (e) {
console.log(JSON.stringify(e))
}
}
//自绘控件解绑输入法
async onDetachInput() {
try {
await this.inputController.detach()
}
catch (e) {
console.log(JSON.stringify(e))
}
}
//绑定输入法输入和删除事件
onInputEvent() {
//输入数字
this.inputController.on("insertText", (text: string) => {
if (text && this.inputCode.length < this.count && !isNaN(Number(text))) {
this.inputCode += text;
}
})
//删除数字
this.inputController.on("deleteLeft", (length: number) => {
this.inputCode = this.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: index === 0 ? 0 : 5, right: index === 5 ? 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 (isVisible && currentRatio >= 1.0) {//页面显示
//延迟200ms兼容绑定失效问题
setTimeout(async()=>{
try {
//绑定输入法和设置聚焦状态弹出键盘
await this.onAttachInput(true)
}
catch (e) {
}
if(this.isFirst){//首次加载
//绑定输入事件
this.onInputEvent()
this.isFirst=false
}
},200)
}
if (!isVisible && currentRatio <= 0.0) {//页面隐藏
//隐藏键盘
this.onAttachInput(false)
}
})
}.width('100%')
}
说明:绘制count(默认6个)个验证码输入框,首次加载绑定键盘输入事件,并通过onVisibleAreaChange事件来辅助判断页面是否跳转或返回(重新显示页面),页面跳转时候隐藏键盘,页面重现时恢复弹出键盘,这边有个坑,在页面返回时候需要延迟绑定输入法弹否则弹出键盘会有异常。
入参有:
iheight:组件高 number|string
iwidth:组件宽 number|string
count 验证码个数 number 默认值6
value 用户输入的验证码 string 双向绑定值
目录:
VerifyCodeInput.ets
import { inputMethod } from '@kit.IMEKit';
@Component
export default struct VerifyCodeInput {
//单个输入框高
@Prop iheight:number|string=48
//单个输入框宽
@Prop iwidth:number|string=48
//验证码字体大小
@Prop fontsize:number|string='20fp'
//验证码框个数
@Prop count:number=6
//输入法客户端实例
private inputController: inputMethod.InputMethodController = inputMethod.getController();
//自绘编辑框配置
private textConfig: inputMethod.TextConfig = {
inputAttribute: {
textInputType: inputMethod.TextInputType.NUMBER, //只能输入数字
enterKeyType: inputMethod.EnterKeyType.GO
},
};
//用户输入的验证码
@Link inputCode: string
//验证码输入框个数数组
@State countArr: number[] = new Array(this.count??6).fill(' ') //count个空元素数组
//是否第一次加载
private isFirst:boolean=true
//自绘控件绑定输入法 @params isFocus:是否聚焦拉起键盘
async onAttachInput(isFocus?:boolean) {
try {
//绑定成功默认拉起键盘
await this.inputController.attach(isFocus??true, this.textConfig);
}
catch (e) {
console.log(JSON.stringify(e))
}
}
//自绘控件解绑输入法
async onDetachInput() {
try {
await this.inputController.detach()
}
catch (e) {
console.log(JSON.stringify(e))
}
}
//绑定输入法输入和删除事件
onInputEvent() {
//输入数字
this.inputController.on("insertText", (text: string) => {
if (text && this.inputCode.length < this.count && !isNaN(Number(text))) {
this.inputCode += text;
}
})
//删除数字
this.inputController.on("deleteLeft", (length: number) => {
this.inputCode = this.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: index === 0 ? 0 : 5, right: index === 5 ? 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 (isVisible && currentRatio >= 1.0) {//页面显示
//延迟200ms兼容绑定失效问题
setTimeout(async()=>{
try {
//绑定输入法和设置聚焦状态弹出键盘
await this.onAttachInput(true)
}
catch (e) {
}
if(this.isFirst){//首次加载
//绑定输入事件
this.onInputEvent()
this.isFirst=false
}
},200)
}
if (!isVisible && currentRatio <= 0.0) {//页面隐藏
//隐藏键盘
this.onAttachInput(false)
}
})
}.width('100%')
}
}
Index.ets
import VerifyCodeInput from '../components/VerifyCodeInput/VerifyCodeInput'
@Entry
@Component
struct Index {
//输入的验证码,双向绑定
@State value:string=''
build() {
Navigation() {
Column() {
VerifyCodeInput({inputCode:this.value})
}.width('100%')
}.title('验证码输入')
.titleMode(NavigationTitleMode.Mini)
}
}
效果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。