news 2026/7/2 0:11:10

【HarmonyOS NEXT】如何监听软键盘的弹出和收起事件

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【HarmonyOS NEXT】如何监听软键盘的弹出和收起事件

一、背景

在开发鸿蒙 APP 登录页时,当输入框键盘弹起,需要改变logo图标与输入框的间距,让整个页面完全展示,提升用户体验

二、具体问题

默认情况下,logo图标与标题栏和输入框给的固定间距,页面能够完全展示,但当键盘弹起时,输入框被遮挡,用户输入了手机号或验证码,但完全看不到自己输入的内容,很影响用户体验

问题效果预览:

问题代码示例如下:

@Extend(TextInput) function commonInputStyle(maxLength: number) { .placeholderColor('#999999') .borderRadius(8) .contentType(ContentType.PHONE_NUMBER) .caretStyle({ color: '#b35336', width: 2 }) .height(48) .maxLength(maxLength) .maxLines(1) .type(InputType.Number) .fontColor('#333333') .width("100%") .backgroundColor(Color.White) .padding({ left: 16, right: 16 }) .shadow({ radius: 4, color: '#00000008', offsetY: 2 }) } @Entry @Component export struct Index { @State phoneNumber: string = "" @State codeNumber: string = "" build() { Column() { Stack({ alignContent: Alignment.Top }) { Column() .width('100%') .height('100%') .backgroundColor('#F8F9FA') // 标题栏 Column() { Text('密码登录') .fontColor('#333333') .fontSize(20) .fontWeight(500) .margin({ top: 10 }) // logo模块 Image($r("app.media.startIcon")) .width(120) .objectFit(ImageFit.Contain) .margin({ top: 110, bottom: 60 }) .borderRadius(16) .shadow({ radius: 8, color: '#00000010', offsetY: 4 }) // 输入模块 Column() { TextInput({ text: this.phoneNumber, placeholder: "请输入手机号" }) .commonInputStyle(11) .onChange((value: string) => { this.phoneNumber = value }) TextInput({ text: this.codeNumber, placeholder: "请输入短信验证码" }) .commonInputStyle(6) .margin({ top: 20 }) .onChange((value: string) => { this.codeNumber = value }) } .width('100%') .padding({ left: 32, right: 32 }) .margin({ top: 200 }) } .width('100%') .height('100%') .justifyContent(FlexAlign.Start) } } .width('100%') .height('100%') } }

三、期望效果

当点击输入框键盘弹起时,改变logo图标与标题栏和输入框的间距,让内容能够完全展现

四、解决方案

4.1、方案1:使用输入框的焦点事件

使用输入框的焦点事件:通过TextInput组件的onFocus和onBlur事件可以间接判断键盘的弹出和收起。当输入框获得焦点时,通常会触发键盘弹出;当输入框失去焦点时,键盘会收起。

@State inputMarginTop: number = 200; // 初始值:无键盘时输入框与logo的间距 @State logoMarginTop: number = 110; //初始值:无键盘时logo与标题的间距 TextInput({ text: this.phoneNumber, placeholder: "请输入手机号" }) .commonInputStyle(11) .onChange((value: string) => { this.phoneNumber = value }) .onFocus(() => { console.log('lucy== 手机号---输入框获焦,键盘已弹出'); this.inputMarginTop = 100 this.logoMarginTop = 50 }) .onBlur(() => { console.log('lucy== 手机号---输入框失焦,键盘已收起'); this.inputMarginTop = 200 this.logoMarginTop = 110 })

备注:此种场景会有个问题,假如有多个输入框,需要给每个输入框都设置焦点事件

4.2、方案2:开启固定态软键盘高度变化的监听

监听键盘高度变化:通过window.on('keyboardHeightChange')事件可以监听键盘的高度变化。当键盘弹出时,返回的高度值为非零值;当键盘收起时,返回的高度值为0。

currentWindow.on('keyboardHeightChange', (data) => { if (data > 0) { console.info('键盘高度大于0,键盘已弹出'); } else { console.info('键盘高度为0,键盘已收起'); } });

完整示例参考如下:

import { KeyboardAvoidMode, window } from '@kit.ArkUI'; @Extend(TextInput) function commonInputStyle(maxLength: number) { .placeholderColor('#999999') .borderRadius(8) .contentType(ContentType.PHONE_NUMBER) .caretStyle({ color: '#b35336', width: 2 }) .height(48) .maxLength(maxLength) .maxLines(1) .type(InputType.Number) .fontColor('#333333') .width("100%") .backgroundColor(Color.White) .padding({ left: 16, right: 16 }) .shadow({ radius: 4, color: '#00000008', offsetY: 2 }) } @Entry @Component export struct Index { @State phoneNumber: string = "" @State codeNumber: string = "" @State inputMarginTop: number = 200; // 初始值:无键盘时输入框与logo的间距 @State logoMarginTop: number = 110; //初始值:无键盘时logo与标题的间距 aboutToAppear(): void { this.getUIContext().setKeyboardAvoidMode(KeyboardAvoidMode.RESIZE); // 设置键盘避让模式 window.getLastWindow(this.getUIContext().getHostContext()).then(currentWindow => { currentWindow.on('keyboardHeightChange', (data) => { if (data > 0) { console.log('lucy== 键盘高度大于0,键盘已弹出'); this.inputMarginTop = 100 this.logoMarginTop = 50 } else { console.log('lucy== 键盘高度为0,键盘已收起'); this.inputMarginTop = 200 this.logoMarginTop = 110 } }); }); } build() { Column() { Stack({ alignContent: Alignment.Top }) { Column() .width('100%') .height('100%') .backgroundColor('#F8F9FA') // 标题栏 Column() { Text('密码登录') .fontColor('#333333') .fontSize(20) .fontWeight(500) .margin({ top: 10 }) // logo模块 Image($r("app.media.startIcon")) .width(120) .objectFit(ImageFit.Contain) .margin({ top: this.logoMarginTop, bottom: 60 }) .borderRadius(16) .shadow({ radius: 8, color: '#00000010', offsetY: 4 }) // 输入模块 Column() { TextInput({ text: this.phoneNumber, placeholder: "请输入手机号" }) .commonInputStyle(11) .onChange((value: string) => { this.phoneNumber = value }) TextInput({ text: this.codeNumber, placeholder: "请输入短信验证码" }) .commonInputStyle(6) .margin({ top: 20 }) .onChange((value: string) => { this.codeNumber = value }) } .width('100%') .padding({ left: 32, right: 32 }) .margin({ top: this.inputMarginTop }) } .width('100%') .height('100%') .justifyContent(FlexAlign.Start) } } .width('100%') .height('100%') } }

4.3、实现效果

实现效果:键盘弹起时输入框不会被遮挡

结论:我选择的是方案二,因为当输入框多的情况下,需要给每个输入框添加焦点事件,而方案二只用监听键盘的高度变化来适配间距,更适合我当下的场景

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 12:32:14

我让AI读了1000个GitHub测试项目,总结出“最佳实践”

‌一、测试工程的四大支柱‌基于对1000 GitHub 测试项目、科技巨头公开文档及行业实践的深度分析,软件测试的最佳实践已形成清晰的四维框架:维度核心实践代表项目/工具关键价值‌测试架构‌测试金字塔(80%单元 15%集成 5%E2E)Go…

作者头像 李华
网站建设 2026/6/26 12:32:37

为什么AI生成的测试用例比人工更“刁钻”?

重新定义“刁钻”测试用例 在软件测试领域,“刁钻”测试用例特指那些能有效暴露隐藏缺陷、覆盖边缘场景的用例,它们往往超出常规逻辑,挑战系统极限。传统人工测试依赖于测试工程师的经验和直觉,但受限于认知偏差和时间压力&#…

作者头像 李华
网站建设 2026/6/28 17:48:16

计算机视觉与机器学习在语音交互中的应用

Alexa & Friends 特邀 Pradeep Natarajan,Alexa AI 首席应用科学家 2021年10月28日,某中心 Alexa AI 团队的首席应用科学家 Pradeep Natarajan 加入了首席 Alexa 技术推广专家 Jeff Blankenburg 的播客节目《Alexa & Friends》,讨论了…

作者头像 李华
网站建设 2026/6/29 9:18:44

Spring Boot 中使用 JSONPath 高效处理 JSON 数据

前言在日常开发中,我们经常需要处理 JSON 数据,特别是从复杂的 JSON 结构中提取特定字段。传统的处理方式如 Gson、Jackson 的 API 虽然功能强大,但在处理复杂路径提取时代码往往显得冗长且不易维护。今天给大家介绍一个更优雅的解决方案 ——…

作者头像 李华
网站建设 2026/6/26 12:32:15

MySQL自增id超过int最大值的场景

点击标题下「蓝色微信名」可快速关注 数据库的主键我们有时候会用自增列,但是自增都会有个上限,如果达到怎么办?技术社群的这篇文章《MySQL自增id超过int最大值怎么办?》就给我们讲解了MySQL数据库自增列达到上限该怎么办&#xf…

作者头像 李华
网站建设 2026/6/26 12:32:21

ssm651网上鲜花店网站vue

目录网上鲜花店网站(Vue框架)摘要开发技术源码文档获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!网上鲜花店网站(Vue框架)摘要 该鲜花店网站基于Vue.js框架开发,结合Spring、SpringM…

作者头像 李华