其他
HarmonyOS 自定义实现验证码框
本文作者
作者:只能写写代码过日子
链接:
https://juejin.cn/post/7329807974968148002
本文由作者授权发布。
如果您有任何疑问、对文章写的不满意、发现错误或者有更好的方法,欢迎在评论、私信或邮件中提出,非常感谢您的支持。PS:二三为错误示例,如果你只想要代码,在四开始。
@Component
struct CodeInputView {
build() {
TextInput()
.backgroundColor("#CCFFFFFF")
.borderRadius(10)
.maxLength(1)
.type(InputType.Number)
.align(Alignment.Center)
}
}
@Preview
@Component
struct CodeInputView {
// 创建一个包含5个空字符串的数组,用于存储输入的数字
@State codeKids: Array<string> = new Array(5).fill('')
// 构建界面
build() {
Row({ space: 10 }) {
ForEach(this.codeKids, (item: string, index: number) => {
TextInput(this.codeKids[index])
.backgroundColor("#CCFFFFFF") // 设置文本输入框的背景颜色
.borderRadius(10) // 设置文本输入框的圆角
.maxLength(1) // 设置最大输入长度为1
.layoutWeight(1) // 设置布局权重
.fontSize(25) // 设置字体大小
.height("100%") // 设置高度为100%
.type(InputType.Number) // 设置输入类型为数字
.align(Alignment.Center) // 设置文本居中对齐
}, (item: string) => item)
}.backgroundColor(Color.Black) // 设置整个行的背景颜色为黑色,方便preview
.height(80) // 设置行的高度为80
}
}
@Preview
@Component
struct CodeInputView {
// 用于存储用户输入的字符的数组,初始值为5个空字符串
@State codeKids: Array<string> = new Array(5).fill('')
// 回调函数,用于传递输入结果给父组件
inputResultCallback: (string) => void
build() {
// 创建一个横向排列的行,每个输入框之间有一定的间隔
Row({ space: vp(10) }) {
ForEach(this.codeKids, (item: string, index: number) => {
TextInput()
.backgroundColor("#CCFFFFFF") // 设置文本输入框的背景颜色
.borderRadius(10) // 设置文本输入框的圆角
.maxLength(1) // 设置最大输入长度为1
.layoutWeight(1) // 设置布局权重
.fontSize(25) // 设置字体大小
.height("100%") // 设置高度为100%
.type(InputType.Number) // 设置输入类型为数字
.align(Alignment.Center) // 设置文本居中对齐
.key(`code${index}`) // 为每个输入框设置唯一的键
.onChange((value) => {
if (value.length <= 1) {
this.codeKids[index] = value // 存储用户输入的字符
}
if (index - 1 < this.codeKids.length) {
let nextIndex = index + 1
// 将焦点自动移动到下一个输入框
focusControl.requestFocus(`code${nextIndex}`)
} else {
// 触发验证码完成回调函数
this.inputResultCallback(this.codeKids.join(""))
}
})
}, (item: string) => item)
}
.backgroundColor(Color.Black) // 设置整个行的背景颜色为黑色
.height(80) // 设置行的高度为80
}
}
检查输入的值长度是否小于等于1,如果是则将该值存储在 codeKids 数组的相应位置上,以保证每个输入框只能输入一个字符。 检查是否还有下一个输入框(index + 1 是否小于 codeKids 数组的长度)。如果有下一个输入框,将焦点自动移动到下一个输入框,以方便用户连续输入。 如果没有下一个输入框,触发 inputResultCallback 回调函数,将输入的值传递给父组件或其他调用者。
3. key属性:为每个 TextInput 组件添加了 key 属性,以确保focusControl.requestFocus的正确触发,这里我们使用了 index 来生成唯一的键。
.defaultFocus(index == 0)
if (value.length <= 1) {
this.codeKids[index] = value
}
.onKeyEvent((event)=>{
if (event.keyCode == KeyCode.KEYCODE_DEL) {
}
})
focusControl.requestFocus(nextKeyStr)
那怎么办呢?
@Preview
@Component
struct CodeInputView {
// 用于存储用户输入的字符的数组,初始值为5个空字符串
@State codeKids: Array<string> = 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 的高度
}
}
.copyOption(CopyOptions.None) // 禁用复制操作
.caretColor(Color.Transparent) // 设置光标为透明
.fontColor(Color.Transparent) // 设置文本颜色为透明
.backgroundColor(Color.Transparent) // 设置背景颜色为透明
// 将输入的字符拆分并分别显示在 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) => {
//做点什么
})
@Preview
@Component
export struct CodeInputView {
@State viewSize: number = 4
inputResultCallback: (string) => void
@Link codeKids: Array<string>
@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))
}
}
最后推荐一下我做的网站,玩Android: wanandroid.com ,包含详尽的知识体系、好用的工具,还有本公众号文章合集,欢迎体验和收藏!
推荐阅读:
扫一扫 关注我的公众号
如果你想要跟大家分享你的文章,欢迎投稿~
┏(^0^)┛明天见!