2024年HarmonyOS一杯冰美式的时间 -- 验证码框(2),2024年最新html5移动开发即学即用网盘

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!


img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化的资料的朋友,可以戳这里获取

         } else {
           // 触发验证码完成回调函数
           this.inputResultCallback(this.codeKids.join(""))
         }
       })
   }, (item: string) => item)
 }
 .backgroundColor(Color.Black) // 设置整个行的背景颜色为黑色
 .height(80) // 设置行的高度为80

}
}


在新的代码中


0. **inputResultCallback属性**:新增了一个名为 `inputResultCallback` 的属性,用于在用户完成输入后将结果传递给父组件。
1. **TextInput的onChange事件**:在每个 `TextInput` 组件中添加了 `onChange` 事件处理程序。当用户输入内容时,这个事件处理程序会被触发。在事件处理程序内部,会进行以下操作:


	* 检查输入的值长度是否小于等于1,如果是则将该值存储在 `codeKids` 数组的相应位置上,以保证每个输入框只能输入一个字符。
	* 检查是否还有下一个输入框(index + 1 是否小于 `codeKids` 数组的长度)。如果有下一个输入框,将焦点自动移动到下一个输入框,以方便用户连续输入。
	* 如果没有下一个输入框,触发 `inputResultCallback` 回调函数,将输入的值传递给父组件或其他调用者。
2. **key属性**:为每个 `TextInput` 组件添加了 `key` 属性,以确保focusControl.requestFocus的正确触发,这里我们使用了 `index` 来生成唯一的键。


### 三、奇怪的问题


0. 输入框没有焦点

 第一次初始化的时候并没有获取焦点,系统也不知道焦点给谁。

 我们只需要在TextInput中加入



.defaultFocus(index == 0)


1. 删除onChange方法并不会触发

 整个流程都已经完成了,包括删除验证码!



if (value.length <= 1) {
this.codeKids[index] = value
}



这段代码赋予了当被删除的时候,数组中的值也会正确的改变。但是!

令人奇怪的是,在当前版本中当进行删除操作的时候,onChange方法并不会触发(平板、模拟器、手机均不会),所以我们需要另寻它法。

监听onKeyEvent!



.onKeyEvent((event)=>{
if (event.keyCode == KeyCode.KEYCODE_DEL) {

}
})


事实上,想法是美好的,这个方法也不会触发(模拟器、平板不触发、手机触发异常)


2. 软键盘显示异常



focusControl.requestFocus(nextKeyStr)



使用requestFocus的确可以将焦点切换到下一个输入框,但是软键盘确收起来了!

在这里我试了很多种办法。都没法做到尽善尽美。

多方查证,也觉得TextInput来做这个应该是不可行的,只能等官方下场修复。

那怎么办呢?


### 四、反过来想 Text() + TextInput()


如果多个输入框有问题,那么我用一个输入框不就行了?于是我就想到了使用多个Text(),一个TextInput的方案。


多个Text()用于排列显示,TextInput用于处理输入


只要显示正常,感知正常,那就没人知道怎么输入进去的~



@Preview
@Component
struct CodeInputView {
// 用于存储用户输入的字符的数组,初始值为5个空字符串
@State codeKids: Array = new Array(5).fill(‘’)

// 回调函数,用于传递输入结果给父组件
inputResultCallback: (string) => void

build() {
// 使用 Stack 布局组织界面元素
Stack() {
if (this.codeKids != null) {
// 创建一个横向排列的行,每个字符之间有一定的间隔
Row({ space: vp(10) }) {
// 使用 ForEach 循环遍历 codeKids 数组
ForEach(this.codeKids, (item: string, index: number) => {
// 显示用户输入的字符
Text(item)
.backgroundColor($r(‘app.color.white_80’)) // 设置背景颜色
.height(match()) // 设置高度匹配内容
.layoutWeight(1) // 设置布局权重
.fontSize(fp(25)) // 设置字体大小
.textAlign(TextAlign.Center) // 设置文本水平居中对齐
.align(Alignment.Center) // 设置垂直居中对齐
.borderRadius(vp(15)) // 设置圆角
.focusable(false) // 不可获得焦点
.defaultFocus(false) // 默认不获得焦点
.focusOnTouch(false) // 不在触摸时获得焦点
}, (item: string) => item)
}
.height(match()) // 设置行的高度匹配内容
.width(match()) // 设置行的宽度匹配内容

// 创建一个输入框用于用户输入
TextInput()
.maxLength(this.viewSize) // 设置最大输入长度
.fontSize(fp(25)) // 设置字体大小
.borderRadius(vp(15)) // 设置圆角
.type(InputType.Number) // 设置输入类型为数字
.key(this.inputKey) // 设置唯一的键
.onChange((value) => {
// 将输入的字符拆分并分别显示在 Text 组件中
let a = value.split(‘’)
this.codeKids.forEach((value, index) => {
this.codeKids[index] = a[index] || ‘’
})
if (a.length >= this.viewSize) {
// 当达到验证码长度时,触发回调函数传递输入结果
this.inputResultCallback(value)
}
// 控制光标显示/隐藏
this.showCaret = (a.length == 0)
})
.copyOption(CopyOptions.None) // 禁用复制操作
.caretColor(this.showCaret ? Color.Black : Color.Transparent) // 设置光标颜色
.fontColor(Color.Transparent) // 设置文本颜色为透明
.backgroundColor(Color.Transparent) // 设置背景颜色为透明
.height(match()) // 设置高度匹配内容
.width(match()) // 设置宽度匹配内容
}
}
.height(vp(80)) // 设置整个 Stack 的高度
}
}


0. TextInput填充布局,置于顶层。文字和背景设置为透明,隐藏光标



.copyOption(CopyOptions.None) // 禁用复制操作
.caretColor(Color.Transparent) // 设置光标为透明
.fontColor(Color.Transparent) // 设置文本颜色为透明
.backgroundColor(Color.Transparent) // 设置背景颜色为透明


1. 添加对应数量的Text,用作显示验证码。这一步其实就是将之前的ForEach中添加的TextInput换为Text即可
2. 在onChange中分隔字符串,并存入对应下标的数组中



// 将输入的字符拆分并分别显示在 Text 组件中
let a = value.split(‘’)
this.codeKids.forEach((value, index) => {
this.codeKids[index] = a[index] || ‘’
})
if (a.length >= this.viewSize) {
// 当达到验证码长度时,触发回调函数传递输入结果
this.inputResultCallback(value)
}


使用也很简单



CodeInputView({inputResultCallback: (code) => {
//做点什么
})


最终效果如下


![](https://img-blog.csdnimg.cn/img_convert/7bdd78cc680cadbaea92cdcc6ca245da.webp?x-oss-process=image/format,png)


### 五、最后


只需要稍微的封装下,将输入框的宽度、高度、圆角、颜色、输入类型、数量等包裹在一个对象中,使用@State修饰,并一一对应应用,即可将这个组件做成一个很标准的任意发挥的输入框啦。


唯一的遗憾是,目前没法去除TextInput点击的样式,除非你是纯色(纯色变化看不出来…)


以下就是该例子代码啦:



@Preview
@Component
export struct CodeInputView {
@State viewSize: number = 4
inputResultCallback: (string) => void
@Link codeKids: Array
@State showCaret: boolean = true
private inputKey = “code_input”

aboutToAppear() {
if (this.codeKids == null) {
this.codeKids = new Array(this.viewSize).fill(‘’);
}
}

build() {
Stack() {
if (this.codeKids != null) {
Row({ space: vp(10) }) {
ForEach(this.codeKids, (item: string, index: number) => {
Text(item)
.backgroundColor($r(‘app.color.white_80’))
.height(match())
.layoutWeight(1)
.fontSize(fp(25))
.textAlign(TextAlign.Center)
.align(Alignment.Center)
.borderRadius(vp(15))
.focusable(false)
.defaultFocus(false)
.focusOnTouch(false)
.onClick(() => {
focusControl.requestFocus(this.inputKey)
})
}, (item: string) => item)
}
.height(match())
.width(match())

TextInput()
.maxLength(this.viewSize)
.fontSize(fp(25))
.borderRadius(vp(15))
.type(InputType.Number)
.key(this.inputKey)
.onChange((value) => {
let a = value.split(‘’)
this.codeKids.forEach((value, index) => {
this.codeKids[index] = a[index] || ‘’
})
if (a.length >= this.viewSize) {
this.inputResultCallback(value)
}
this.showCaret = (a.length == 0)
})
.copyOption(CopyOptions.None)
.caretColor(this.showCaret ? Color.Black : Color.Transparent)
.fontColor(Color.Transparent)
.backgroundColor(Color.Transparent)
//TODO 系统问题,如果背景色是透明的也没用,非透明可以
// .stateStyles({ pressed: {.backgroundColor(“跟背景一样的颜色(纯透明会黑色闪一下)”)}})
.height(match())
.width(match())
}
}
.height(vp(80))
}
}


### 六、总结


这个需求大概就告一段了,如果各位有什么想加的功能啥的,可以在评论区告知哦。


总之,HarmonyOS ArkUI的文档还是太少了,很多API都需要摸索,很多写法、操作都不习惯。以及很多坑!,Android的思维不适用在HarmonyOS。


**为了能让大家更好的学习鸿蒙 (OpenHarmony) 开发技术,这边特意整理了《鸿蒙 (OpenHarmony)开发学习手册》(共计890页),希望对大家有所帮助:[`https://qr21.cn/FV7h05`]( )**


### 《鸿蒙 (OpenHarmony)开发学习手册》


#### 入门必看:[`https://qr21.cn/FV7h05`]( )


**深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

![](https://img-blog.csdnimg.cn/direct/743b668910224b259a5ffe804fa6d0db.png)
![img](https://img-blog.csdnimg.cn/img_convert/a70b07d40f57994aae218aa8354c53ac.png)
![img](https://img-blog.csdnimg.cn/img_convert/90bd41aff2e455359a0f97b0517b7cfd.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618636735)**

g.csdnimg.cn/direct/743b668910224b259a5ffe804fa6d0db.png)
[外链图片转存中...(img-EdhqVYVf-1715610527522)]
[外链图片转存中...(img-L9qXsVj5-1715610527522)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618636735)**

  • 30
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值