参考示例://Index.est import { router } from '@kit.ArkUI'; @Entry @Component struct Index { build() { Row() { Column() { Button('使用系统键盘') .onClick(() => { router.pushUrl({ url: 'pages/SystemKeyboard' }) }) .margin({ bottom: 20 }) Button('使用自定义键盘') .onClick(() => { router.pushUrl({ url: 'pages/CustomKeyboard' }) }) } .width('100%') } .height('100%') } }//CommonPage.ets @Component export struct CommonPage { build() { Row() { Column() { Navigation() { Row() { Text('登录账号') Text('156****5163') } .width('90%') .justifyContent(FlexAlign.SpaceBetween) .alignItems(VerticalAlign.Center) .padding({ bottom: 20 }) .border({ width: { bottom: 1 }, color: '#ccc' }) .margin({ top: 20, bottom: 20 }) Row() { Text('切换账号') Image($r('app.media.right')) .width(20) } .width('90%') .justifyContent(FlexAlign.SpaceBetween) .alignItems(VerticalAlign.Center) .padding({ bottom: 20 }) .border({ width: { bottom: 1 }, color: '#ccc' }) } .hideTitleBar(false) .titleMode(NavigationTitleMode.Mini) .title('个人中心设置') } .width('100%') .height('100%') } .height('100%') } }//CustomKeyboard.ets import { CommonPage } from './CommonPage'; export interface commonBorder { width?: Length | EdgeWidths, color?: ResourceColor | EdgeColors, radius?: Length | BorderRadiuses, style?: BorderStyle | EdgeStyles } @Entry @Component struct CustomKeyboard { // 展示的text @State @Watch('setValue') codeTxt: string = ''; // 屏幕宽度 @State screenWidth: number = 0; @State isShow: boolean = false @State inputValue: string = '' // 最大长度 @State maxLength: number = 6; @State Index: number[] = [0, 1, 2, 3, 4, 5] // 控制动画的 @State showMouse: boolean[] = []; controller: TextInputController = new TextInputController() // 未选中的样式 private btnCancelBorder?: commonBorder = { width: '3px', color: '#ccc', style: BorderStyle.Solid } // 选中的样式 private btnCancelBorderActive: commonBorder = { width: '3px', color: Color.Red, style: BorderStyle.Solid } aboutToAppear(): void { console.info('IsaKit aboutToAppear') this.screenWidth = 1080; this.showMouse = new Array(this.maxLength).fill(false); } setValue() { if (this.codeTxt) { this.handelInputTxt(this.codeTxt.length, this.codeTxt); } else { this.handelInputTxt(0, ''); } } // 改变输入框选中的值 handelInputTxt(length: number, val: string) { length === this.maxLength ? this.showMouse.fill(false) : this.showMouse.fill(false).splice(length - 1, 0, true); console.log('----length', length) console.info('----this.showMouse', JSON.stringify(this.showMouse)); console.log('---value', val) } // 自定义键盘样式 @Builder CustomKeyboardBuilder() { Column() { Grid() { ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, '*', 0, '#'], (item: number | string) => { GridItem() { Button(item + '') .width(110).onClick(() => { this.codeTxt += item }) } }) }.maxCount(3).columnsGap(10).rowsGap(10).padding(5) }.backgroundColor(Color.Gray) Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceEvenly }) { Button('关闭').width('30%') .onClick(() => { // 关闭自定义键盘 this.controller.stopEditing() }) Button().width('30%').opacity(0) Button('删除').width('30%') .onClick(() => { this.codeTxt = this.codeTxt.slice(0, -1) console.info('this.inputText', 'deleteLeft this.inputText===' + this.codeTxt) }) } .padding(5) } // 拉起的半模态样式 @Builder bindSheetBuilder() { Column() { Text('填写手机短信验证码') .fontWeight(FontWeight.Bold) .margin({ top: 20, bottom: 20 }) Row() { Text() { Span('已发送至') .fontSize(12) .fontWeight(400) .fontColor(Color.Grey) } Blank().width(5) Text() { Span('156****5163') .fontSize(12) .fontWeight(500) .fontColor(Color.Black) } }.width('100%') .justifyContent(FlexAlign.Start) .padding({ left: 20, right: 20 }) .margin({ bottom: 20 }) // 展示验证码 this.buildAEnterCodeInput() } } // 公共页面,点击即可拉起半模态 @Builder buildTitleName() { CommonPage() .onClick(() => { this.isShow = true }) .bindSheet($$this.isShow, this.bindSheetBuilder, { height: '70%', blurStyle: BlurStyle.Thick, showClose: false, preferType: SheetType.CENTER }) } @Builder componentBuilder() { Column() { this.buildTitleName() Blank().height(38) this.buildAEnterCodeInput() Blank().height(20) } .margin({ top: 10 }) .borderRadius(8) .backgroundColor(Color.White) } // 验证码的样式 @Builder buildAEnterCodeInput() { Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) { Column() { Row() { Text(this.codeTxt[0]) .fontSize(18) .fontWeight(600) .textAlign(TextAlign.Center) .width(50) .height(50) .margin({ left: 5, right: 5 }) .border(this.showMouse[this.Index[0]] ? this.btnCancelBorderActive : this.btnCancelBorder) .borderRadius(5) Text(this.codeTxt[1]) .fontSize(18) .fontWeight(600) .textAlign(TextAlign.Center) .width(50) .height(50) .margin({ left: 5, right: 5 }) .border(this.showMouse[this.Index[1]] ? this.btnCancelBorderActive : this.btnCancelBorder) .borderRadius(5) Text(this.codeTxt[2]) .fontSize(18) .fontWeight(600) .textAlign(TextAlign.Center) .width(50) .height(50) .margin({ left: 5, right: 5 }) .border(this.showMouse[this.Index[2]] ? this.btnCancelBorderActive : this.btnCancelBorder) .borderRadius(5) Text(this.codeTxt[3]) .fontSize(18) .fontWeight(600) .textAlign(TextAlign.Center) .width(50) .height(50) .margin({ left: 5, right: 5 }) .border(this.showMouse[this.Index[3]] ? this.btnCancelBorderActive : this.btnCancelBorder) .borderRadius(5) Text(this.codeTxt[4]) .fontSize(18) .fontWeight(600) .textAlign(TextAlign.Center) .width(50) .height(50) .margin({ left: 5, right: 5 }) .border(this.showMouse[this.Index[4]] ? this.btnCancelBorderActive : this.btnCancelBorder) .borderRadius(5) Text(this.codeTxt[5]) .fontSize(18) .fontWeight(600) .textAlign(TextAlign.Center) .width(50) .height(50) .margin({ left: 5, right: 5 }) .border(this.showMouse[this.Index[5]] ? this.btnCancelBorderActive : this.btnCancelBorder) .borderRadius(5) } .onClick(() => { focusControl.requestFocus('TextInput') }) TextInput({ controller: this.controller, text: $$this.inputValue }) .width('100%') .height(100) .opacity(0) .id('TextInput') .customKeyboard(this.CustomKeyboardBuilder()) .onChange((value) => { this.codeTxt = value if (this.codeTxt.length >= 6) { return } this.codeTxt += this.inputValue; console.info('----codeTxt' + this.codeTxt) }) } } .backgroundColor(Color.White) .height(50) .margin({ left: 15, right: 15 }) .id('customInput') .defaultFocus(false) } build() { Column() { this.componentBuilder() } } }//SystemKeyboard.ets /* * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. */ import inputMethod from '@ohos.inputMethod'; import { BusinessError } from '@ohos.base'; import { CommonPage } from './CommonPage' @Entry @Component struct SystemKeyboard { // 输入的验证码 @State codeTxt: string = ''; // 初始化屏幕宽度 @State screenWidth: number = 0; // 模态窗口是否展示 @State isShow: boolean = false private isAttached: boolean = false; private inputController: inputMethod.InputMethodController = inputMethod.getController(); private keyboardStatus: number = 0; // 默认是none, 1是hide,2是show aboutToAppear(): void { console.info('IsaKit aboutToAppear') this.screenWidth = 1080; } @Builder componentBuilder() { Column() { this.buildTitleName() Blank().height(38) this.buildAEnterCodeInput() Blank().height(20) } .margin({ top: 10 }) .borderRadius(8) .backgroundColor(Color.White) } // 模态弹窗样式 @Builder bindSheetBuilder() { Column() { Text('填写手机短信验证码') .fontWeight(FontWeight.Bold) .margin({ top: 20, bottom: 20 }) Row() { Text() { Span('已发送至') .fontSize(12) .fontWeight(400) .fontColor(Color.Grey) } Blank().width(5) Text() { Span('156****5163') .fontSize(12) .fontWeight(500) .fontColor(Color.Black) } }.width('100%') .justifyContent(FlexAlign.Start) .padding({ left: 20, right: 20 }) .margin({ bottom: 20 }) this.buildAEnterCodeInput() } } // 拉起模态弹窗 @Builder buildTitleName() { CommonPage() .onClick(() => { this.isShow = true }) .bindSheet($$this.isShow, this.bindSheetBuilder, { height: '70%', blurStyle: BlurStyle.Thick, showClose: false, preferType: SheetType.CENTER }) } // 单个验证码的格式 @Styles fancyUse(){ .width((this.screenWidth - 110) / 6) .height('100%') .margin({ left: 5, right: 5 }) .border({ width: 0.5, color: Color.Grey, style: BorderStyle.Solid }) .borderRadius(5) } @Builder buildAEnterCodeInput() { Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) { Text(this.codeTxt[0]) { } .fontSize(18) .fontWeight(600) .textAlign(TextAlign.Center) .fancyUse() Text(this.codeTxt[1]) .fontSize(18) .fontWeight(600) .textAlign(TextAlign.Center) .fancyUse() Text(this.codeTxt[2]) .fontSize(18) .fontWeight(600) .textAlign(TextAlign.Center) .fancyUse() Text(this.codeTxt[3]) .fontSize(18) .fontWeight(600) .textAlign(TextAlign.Center) .fancyUse() Text(this.codeTxt[4]) .fontSize(18) .fontWeight(600) .textAlign(TextAlign.Center) .fancyUse() Text(this.codeTxt[5]) .fontSize(18) .fontWeight(600) .textAlign(TextAlign.Center) .fancyUse() } .backgroundColor(Color.White) .height(50) .margin({ left: 15, right: 15 }) .id('customInput') .defaultFocus(false) .onVisibleAreaChange([0.0, 1.0], (isVisible: boolean, currentRatio: number) => { console.info('IsaKit Test Text isVisible: ' + isVisible + ', currentRatio:' + currentRatio) if (isVisible && currentRatio >= 1.0) { console.info('IsaKit Test Text is fully visible. currentRatio:' + currentRatio) this.attachAndListener(); } if (!isVisible && currentRatio <= 0.0) { console.info('IsaKit Test Text is completely invisible.') this.detach() } }) .onClick(async () => { console.info('IsaKit keyboardStatus =' + this.keyboardStatus) if (this.isAttached && this.keyboardStatus != 2) { // 输入法配置项 let textConfig: inputMethod.TextConfig = { inputAttribute: { textInputType: inputMethod.TextInputType.NUMBER, enterKeyType: inputMethod.EnterKeyType.GO } }; // 控件绑定输入法 await this.inputController.attach(true, textConfig) return } }) } // 解绑输入法 detach() { this.inputController.off('insertText'); this.inputController.off('deleteLeft'); this.inputController.off('sendKeyboardStatus'); this.inputController.detach((err: BusinessError) => { if (err) { console.error(`Failed to detach: ${JSON.stringify(err)}`); return; } this.isAttached = false console.log('Succeeded in detaching inputMethod.'); }); } // 绑定和设置监听 async attachAndListener() { // 输入法配置项 let textConfig: inputMethod.TextConfig = { inputAttribute: { textInputType: inputMethod.TextInputType.NUMBER, enterKeyType: inputMethod.EnterKeyType.GO } }; // 控件绑定输入法 await this.inputController.attach(true, textConfig) this.isAttached = true this.attachListener() } /* * 订阅输入法回调 */ attachListener(): void { // 订阅输入法应用插入文本事件 this.inputController.on('insertText', (text) => { if (this.codeTxt.length >= 6) { return } this.codeTxt += text; console.info('this.inputText', 'insertText this.inputText===' + this.codeTxt) }) // 订阅输入法应用向左删除事件 this.inputController.on('deleteLeft', (length) => { this.codeTxt = this.codeTxt.substring(0, this.codeTxt.length - 1); console.info('this.inputText', 'deleteLeft this.inputText===' + this.codeTxt, 'length' + length) }) // 订阅输入法应用发送输入法软键盘状态事件 this.inputController.on('sendKeyboardStatus', (keyboardStatus: inputMethod.KeyboardStatus) => { this.keyboardStatus = keyboardStatus console.info('IsaKit this.inputText keyboardStatus= ' + this.keyboardStatus) }) } build() { Column() { this.componentBuilder() } } }
参考示例: