「HarmonyOS」验证码多TextInput输入框焦点自动跳转问题

需求背景:需要做一个多输入框的验证码模块,输入验证码时输入后光标会自动跳转至下一个输入框,删除验证码时会自动删除上一个输入框内容,并且光标跳转至上一个输入框内。6位验证码全部输完后进行登录请求

具体样式如下图:

在这里插入图片描述

具体实现效果如下图:

在这里插入图片描述

思路分析:

1.组件化

这个验证码输入框每个都样式和交互逻辑都非常相似,将其提取出作为组件化编写,减少代码冗余,先将单个输入框的样式进行编写

@Component
struct codeInputView {code: stringkeyNo: numberkeyStr: stringbuild() {Row() {Column() {TextInput({text: this.code}).backgroundColor($r('app.color.smart_F5F5F5')).maxLength(1).type(InputType.Number).align(Alignment.Center).width((screenWidthPxToVp - 87)/6 - 10)}.width((screenWidthPxToVp - 87)/6)}.height(55).backgroundColor($r('app.color.smart_F5F5F5')).borderRadius(8)}
}
2.实现输入的时候,输入后光标跳转至下一个输入框

通过查阅开发文档和相关资料,发现可以将focusControl和key配合使用进行切换聚焦组件,切换焦点

相关资料链接

// 自定义输入框组件
@Component
struct codeInputView {@State code:stringkeyNo: numberkeyStr: string// 将code值传递到外部transfer: (number) => void// 登录请求回调requestAction?: ()=>voidbuild() {Row() {Column() {TextInput({text: this.code}).backgroundColor($r('app.color.smart_F5F5F5')).maxLength(1).type(InputType.Number).align(Alignment.Center).width((screenWidthPxToVp - 87)/6 - 10).onChange((value) => {if (value.length == 1) {// 当输入框中有验证码输入// 当不是最后一个输入框时,焦点跳转到下一个输入框if (this.keyNo != 5) {// 验证码赋值this.code = value// 验证码传递至外部this.transfer(value)// 切换焦点到下一个输入框let nextKeyNo: number = this.keyNo + 1let nextKeyStr = 'code' + nextKeyNoLog.info('nextKeyStr = ' + nextKeyStr)focusControl.requestFocus(nextKeyStr)} else {// 当最后一个输入框时,传值并且进行登录请求回调this.transfer(value)this.requestAction()}}}).onFocus(() => {// 获取焦点时进行日志打印查看Log.info('get focus = ' + this.keyStr)})// 设置输入框key值.key(this.keyStr)}.width((screenWidthPxToVp - 87)/6)}.height(55).backgroundColor($r('app.color.smart_F5F5F5')).borderRadius(8)}
}// 页面代码
@Entry
@Component
export default struct VerifyLoginPage {private inputVerify: string = '请输入验证码'private hadSentToPhone: string = '已发送验证码到您的手机号'private code0: stringprivate code1: stringprivate code2: stringprivate code3: stringprivate code4: stringprivate code5: string@State phone: string = ''onPageShow() {this.phone = router.getParams()?.['phone']}build() {Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Start}) {Image($r('app.media.back_icon')).size({width: 33, height: 33}).onClick(() => {Log.info('click back button')router.back()})Text(this.inputVerify).textStyle(25, $r('app.color.smart_24292B'), FontWeight.Medium).margin({top: 32})Text(this.hadSentToPhone + this.phone).textStyle(14, $r('app.color.smart_9DA2A5'), FontWeight.Regular).margin({top: 12})// 验证码输入框Flex({direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.SpaceBetween}) {codeInputView({keyNo: 0, keyStr: 'code0', transfer: (num)=>{this.code0 = num}})codeInputView({keyNo: 1, keyStr: 'code1', transfer: (num)=>{this.code1 = num}}).margin({left: 11})codeInputView({keyNo: 2, keyStr: 'code2', transfer: (num)=>{this.code2 = num}}).margin({left: 11})codeInputView({keyNo: 3, keyStr: 'code3', transfer: (num)=>{this.code3 = num}}).margin({left: 11})codeInputView({keyNo: 4, keyStr: 'code4', transfer: (num)=>{this.code4 = num}}).margin({left: 11})codeInputView({keyNo: 5, keyStr: 'code5', transfer: (num)=>{this.code5 = num}, requestAction: ()=>{this.loginRequest()}}).margin({left: 11})}.margin({top: 80})}.width('100%').padding({left: 16, right: 16})}// 登录请求
loginRequest() {let code = this.code0 + this.code1 + this.code2 + this.code3 + this.code4 + this.code5Log.info('phone = ' + this.phone)Log.info('code = ' + code)// 登录网络请求// xxxxxxx
}

此时,可以实现当输入后,光标可以跳转至下一个输入框中,并且可以将输入的code传递至组件外部进行存储在页面中

3.实现删除时,删除前一个输入框内容,并且光标跳转至前一个输入框中

通过日志打印发现,输入删除按钮,onChange方法无法获取到删除的value值。于是通过查看开发文档,发现可以通过onKeyEvent(event: KeyEvent) => {}方法,获取到删除指令,并且通过打印日志发现,每次点击删除按键,都会执行两次删除方法。

这在一开始非常奇怪和难受,因为我想用同样key的值递减来控制光标的移动,而每次删除时,都会往前跳两个输入框,并且输入框的内容不会删除,所以由此我想到可以一次删除方法来进行光标跳转,一次删除方法用来删除输入框的内容。

以下为更新后最终代码

@Component
struct codeInputView {@State code: string = ''keyNo: numberkeyStr: stringtransfer: (number) => voidrequestAction?: ()=>voidbuild() {Row() {Column() {TextInput({text: this.code}).backgroundColor($r('app.color.smart_F5F5F5')).maxLength(1).type(InputType.Number).align(Alignment.Center).width((screenWidthPxToVp - 87)/6 - 10).onChange((value) => {if (value.length == 1) {if (this.keyNo != 5) {let nextKeyNo: number = this.keyNo + 1let nextKeyStr = 'code' + nextKeyNoLog.info('nextKeyStr = ' + nextKeyStr)this.code = valuethis.transfer(value)focusControl.requestFocus(nextKeyStr)} else {this.transfer(value)this.requestAction()}}}).onFocus(() => {Log.info('get focus = ' + this.keyStr)Log.info('thisCode = ' + this.code)})// 删除验证码时执行的方法回调.onKeyEvent((event: KeyEvent) => {if (event.keyCode == KeyCode.KEYCODE_DEL) {// 当code值不为空时,删除code值if (this.code != '') {this.code = ''} else if (this.keyNo > 0) {// 如果不是第一个输入框,则每次递减keyNo使光标进行跳转至前一个输入框内let preKeyNo: number = this.keyNo - 1let preKeyStr = 'code' + preKeyNoLog.info('preKeyStr = ' + preKeyStr)focusControl.requestFocus(preKeyStr)}}}).key(this.keyStr)}.width((screenWidthPxToVp - 87)/6)}.height(55).backgroundColor($r('app.color.smart_F5F5F5')).borderRadius(8)}
}// 页面代码
// 页面代码与第2点相同,在此不过多赘述

此次在codeInputView组件的初始化中code值有进行修改,添加了’'空字符串,这是因为通过打印日志发现,如果不进行赋值的初始化时,code值会为undefined,这个在删除code值时会非常奇怪,所以进行了设空字符串进行初始化

最终即可实现需求所要求的交互逻辑

当前HarmonyOs仍在初步学习过程中,大家如果感兴趣或者有问题可以一起沟通交流,目前在学习过程中也遇到一些HarmonyOs开发组件上的一些小bug,希望华为可以及时进行更新修复!努力并大步的发展我们国家自己的移动端系统,遥遥领先!

如果该文章对你有所帮助的话,可以点赞、收藏并关注一下!后续会持续更新更多技术内容

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/322896.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C练习——定期存取并行

题目:假设银行一年整存零取的月息为1.875%,现在某人手头有一笔钱,他打算在今后5年 中,每年年底取出1000元作为孩子来年的教育金,到第5年孩子毕业时刚好取完这笔钱,请编 程计算第1年年初时他应存入银行多少钱…

无法到达所选择的在线目标(博途PLC连接不上)

第1步:首先需要检查的就是PLC的物理连接了,可以利用PING工具测试下电脑和PLC是否在同一个网段, 第2步就是检查下防火墙设置 1、防火墙设置 2、关闭防火墙 未完....

用C语言采集游戏平台数据并做行业分析

游戏一直深受90/00后的喜爱,有些人因为对游戏的热爱还专门成立了工作室做游戏赚钱,但是游戏行业赚钱走不好就会被割一波韭菜,那么现在什么游戏挣钱,什么游戏好玩认可度高?带着这样的问题我将利用我毕生所学&#xff0c…

RA8803SA 车载用实时时钟模块

内置32.768kHz 晶体单元(频率精度调整完毕)和DTCXO1/100s精度的时间寄存器接口类型:I2C-Bus接口(400kHz)工作电压范围:1.6V to 5.5V温度补偿电压:2.2V to 5.5V计时(保持)电压范围:1.6V to 5.5V可选择输出频率为32.768kHz, 1024Hz,…

华为云Stack 8.X流量模型分析(六)

八、基础云专线流量模型分析 ​ 华为官方对云专线定义是:用户数据中心通过运营商的物理专线(MPLS/VPN,以太专线)访问云内资源,云内资源呈现真实IP,通过设置的专线路由实现三层互通。 ​ 通过云专线直接访…

yolov8实战第五天——yolov8+ffmpg实时视频流检测并进行实时推流——(推流,保姆教学)

yolov8实战第一天——yolov8部署并训练自己的数据集(保姆式教程)_yolov8训练自己的数据集-CSDN博客 yolov8实战第三天——yolov8TensorRT部署(python推理)(保姆教学)-CSDN博客 今天,我们继续y…

目标检测-One Stage-EfficientDet

文章目录 前言一、EfficientNetEfficientNet-B0 baselineMBConv 参数优化EfficientNet B0-B7 参数 二、EfficientDetBiFPN复合缩放方法 总结 前言 EfficientDet是google在2019年11月发表的一个目标检测算法系列,其提出的背景是:之前很多研究致力于开发更…

论文阅读: Semantics-guided Triplet Loss

ICCV 2021 Abstract 一个度量学习方法,通过浏览语义引导的局部集合去优化内在深度表示。一个新颖的特征融合模块能有效利用跨模态特异质特征。 Senantics-guided Triplet Loss 基本假设: 在场景语义分割图像中,目标内部相邻像素拥有同样…

【数据结构】平衡二叉树

导语 对于二叉搜索树 而言,它的 增、 删 、 改 、 查 的时间复杂度为 O() ~ O(n) 。原因是最坏情况下,二叉搜索树会退化成 线性表 。换言之,树的高度决定了它插入、删除和查找的时间复杂度。 为了对上述缺点进一步优化,设计了一…

基于gamma矫正的照片亮度调整(python和opencv实现)

import cv2 import numpy as npdef adjust_gamma(image, gamma1.0):invGamma 1.0 / gammatable np.array([((i / 255.0) ** invGamma) * 255 for i in np.arange(0, 256)]).astype("uint8")return cv2.LUT(image, table)# 读取图像 original cv2.imread("tes…

Redis命令---List篇

目录 1.Redis Lindex 命令 - 通过索引获取列表中的元素简介语法可用版本: > 1.0.0返回值: 列表中下标为指定索引值的元素。 如果指定索引值不在列表的区间范围内,返回 nil 。 示例 2.Redis Rpush 命令 - 在列表中添加一个或多个值简介语法可用版本: > 1.0.0返…

注意!2024年中科院预警名单将于本月发布!(附往期名单+分区表下载)

2024年中科院预警期刊何时发布 2023年12月27日,《2023年中国科学院文献情报中心期刊分区表》正式发布! 此次分区表发布有几项重要变动: 👉可参考:2023中科院分区期刊变动情况 重磅!2023年中科院分区表最…