HarmonyOS开发案例-界面组件在软键盘弹出时避免遮挡

场景说明

在应用开发中,我们经常会遇到这样的场景:当我们点击一个输入框时,系统会自动弹出软键盘,但是软键盘却会遮挡住输入框或者其他重要的控件。为了解决这个问题,现有的常用策略会在软键盘弹出时,根据输入框的位置,把整个页面向上移动一段距离,从而让输入框能够完全显示在屏幕上。然而,这种方法并不完美,其他控件比如确认按钮仍有可能被软键盘挡住,使得用户无法完成操作。本案例将针对此问题提供一种简单而有效的解决方案。

效果呈现

运行环境

本例基于以下环境开发,开发者也可基于其他适配的版本进行开发:

  • IDE: DevEco Studio 3.1.1 Release
  • SDK: 3.1.0(API 9)

实现思路

要想解决页面遮挡的问题,我们首先要了解它的原因:当我们点击输入框时,系统会弹出软键盘,这时候软键盘会占用一部分屏幕空间,导致显示区域和软键盘区域重叠。软键盘区域属于系统规避区域。除了软键盘区域之外,还有一些其他的系统规避区域,比如状态栏、刘海屏和手势区域等。如果想让应用能够适应这些系统规避区域的变化,我们需要监听这些区域的变化事件并且根据这些区域的尺寸,动态地调整应用的显示区域,重新绘制页面。

开发步骤

  1. 创建一个简单的输入验证码界面,它包含了文本框、输入框和确认按钮。这个界面的问题是,当我们点击输入框时,系统会弹出软键盘,但是软键盘却会挡住确认按钮,使得我们无法完成操作。
@Entry
@Component
struct Index {
  @State screenHeight: number = 0;
  build() {
    Row() {
      Column() {
        Text('请输入短信验证码')
          .fontSize(30)
          .margin({
            bottom:'50'
          })
        TextInput()
          .width('70%')
          .height('150px')
          .margin({
            bottom: '30'
          })
        Button('确定')
          .width('70%')
          .margin('20px')
      }
      .width('100%')
    }
    .width('100%')
    .height('100%')
  }
}
  1. 创建一个变量screenHeight,并把它赋值为当前显示区域的高度。这样,我们就可以在后面根据需要来修改这个变量的值,从而改变显示区域的高度。
@State screenHeight: number = 0;

window.getLastWindow(getContext(this)).then(currentWindow =>{
      let property = currentWindow.getWindowProperties();
      let avoidArea = currentWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_KEYBOARD);
      // 初始化显示区域高度
      this.screenHeight = px2vp(property.windowRect.height - avoidArea.bottomRect.height);
    })
})
  1. 监听系统规避区域的变化事件,判断是否是由于软键盘的弹出或收起导致的。如果是,则就获取软键盘的高度。然后,将screenHeight的值设置为原始高度减去软键盘的高度。这样,显示区域就会缩小,避免和软键盘重叠。
window.getLastWindow(getContext(this)).then(currentWindow =>{
    let property = currentWindow.getWindowProperties();
    currentWindow.on('avoidAreaChange', async data => {
        if (data.type !== window.AvoidAreaType.TYPE_KEYBOARD) {
            return;
        }
        this.screenHeight = px2vp(property.windowRect.height - data.area.bottomRect.height);
    })
})

完整代码

import window from '@ohos.window';

@Entry
@Component
struct Index {
 @State screenHeight: number = 0;

 aboutToAppear() {
   window.getLastWindow(getContext(this)).then(currentWindow =>{
     let property = currentWindow.getWindowProperties();
     let avoidArea = currentWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_KEYBOARD);
     // 初始化显示区域高度
     this.screenHeight = px2vp(property.windowRect.height - avoidArea.bottomRect.height);
     // 监视软键盘的弹出和收起
     currentWindow.on('avoidAreaChange', async data => {
       if (data.type !== window.AvoidAreaType.TYPE_KEYBOARD) {
         return;
       }
       this.screenHeight = px2vp(property.windowRect.height - data.area.bottomRect.height);
     })
   })
 }

 build() {
   Row() {
     Column() {
       Text('请输入短信验证码')
         .fontSize(30)
         .margin({
           bottom:'50'
         })
       TextInput()
         .width('70%')
         .height('150px')
         .margin({
           bottom: '30'
         })
       Button('确定')
         .width('70%')
         .margin('20px')
     }
     .width('100%')
   }
   .width('100%').height(this.screenHeight)
 }
}
赞 (4) 打赏