一、背景
在开发鸿蒙登录/验证码页面时,需要实现「每个数字单独占一格、每格下方带下划线、输入框隐藏」的手机号或验证码输入效果。
最初我是打算用输入框TextInput+下划线Divider来实现这个效果的,但是无法实现「单格单字符+独立下划线」的视觉效果,最终采用以下的实现思路
需要实现的效果图:
二、实现思路
以11位手机号码为例:
1、UI视觉:通过ForEach循环渲染 11 个由Column包裹的 “Text+Divider” 组合,实现 单格数字+下划线的效果。
2、交互实现:隐藏的TextInput处理实际输入和数据绑定
3、点击控制:当点击输入数字时,通过focusControl将焦点传递给隐藏的TextInput,确保输入的连贯性
三、具体代码如下
以下代码可直接运行查看效果
@Entry @ComponentV2 struct Index { @Local phoneNumber: string = "" private inputKey: string = "mobileFocus" controller: TextInputController = new TextInputController() build() { Column() { Stack({ alignContent: Alignment.Center }) { // 1. 交互层:隐藏的TextInput(处理输入逻辑) TextInput({ text: this.phoneNumber, controller: this.controller }) .fontSize(16) .opacity(0) .type(InputType.Number) .height('auto') .key(this.inputKey) .textAlign(TextAlign.Center) .maxLength(11) .onChange((value) => { this.phoneNumber = value }) //2. UI层:TextAndLine组件(渲染11个格子) TextAndLine({ count: 11, chat: this.phoneNumber, textWidth: 20, dividerWidth: 24 }) } .margin({ top: 100 }) .onClick(() => { focusControl.requestFocus(this.inputKey) }) } .width('100%') .height('100%') .backgroundColor('#151617') } } @ComponentV2 export struct TextAndLine { @Param chat: string = "" @Param count: number = 11 @Param textWidth: number = 20 @Param dividerWidth: number = 24 private dataArray: string[] = new Array(this.count).fill(null) build() { Row({ space: 8 }) { ForEach(this.dataArray, (value: string, index: number) => { Column() { Text(this.getValue(index)) .width(this.textWidth) .height(44) .lineHeight(44) .fontColor('#CCFFFFFF') .fontSize(32) .textAlign(TextAlign.Center) Divider() .strokeWidth(1) .color('#99FFFFFF') .width(this.dividerWidth) }.justifyContent(FlexAlign.Center) }) } .width('auto') .height(60) .backgroundColor('#FF151617') } getValue(index: number): string { if (this.chat.length > index) { return this.chat[index].toString() } else { return " " } } }