软键盘弹出时,页面的自适应

软键盘弹出时,页面的自适应

HarmonyOS
2024-05-26 11:25:50
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
wjmfzsz

本文主要介绍当软键盘弹出时,输入框与页面的自适应。

典型的使用场景如下:

  • 场景1:当输入框在底部时,软键盘弹出会如何保证页面顶部标题栏不会被挤出去而是压缩页面可滚动内容区域。相关开发场景:即时通讯APP,消息框在底部,消息列表为滚动区域,用户昵称为标题栏。
  • 场景2:当输入框在顶部时,软键盘弹出如何保证不会遮挡内容显示。相关开发场景:搜索框相关开发场景,当需要联想搜索数据时。

使用的核心API

安全区域

getLastWindow

avoidAreaChange

核心代码解释

场景一:输入框在底部时,保证顶部标题栏不被顶出去

实现思路:当我们点击输入框时,系统会弹出软键盘,这时候软键盘会占用一部分屏幕空间,当我们设置了安全区域expandSafeArea后,会导致页面整个被挤出去,但是一般的移动端逻辑,还需要保持tabHeader不能被顶出去,通过自定义的tab实现了述求。

@Entry 
@Component 
struct SafeAreaExample { 
  @State text: string = '' 
  @State list: number[] = [] 
  controller: TextInputController = new TextInputController() 
  aboutToAppear() { 
    for (let index = 0; index < 20; index++) { 
      this.list.push(index) 
    } 
  } 
   
  @Builder 
  TabHeader(text = '') { 
    Text(text).fontSize(30).fontColor(Color.Red).expandSafeArea([SafeAreaType.KEYBOARD]) 
  } 
   
  build() { 
    Flex({ direction: FlexDirection.Column }) { 
      Row() { 
        Text("顶部标题栏内容,我不能被顶出去") 
      } 
      .width('100%') 
      .height(50) 
      .backgroundColor(Color.Pink) 
      .padding({ left: 20, right: 20 }) 
      .zIndex(99) 
      .expandSafeArea([SafeAreaType.KEYBOARD]) // 配置键盘弹出安全区域 
      Tabs() { 
        TabContent() { 
          List({ space: 20 }) { 
            ForEach(this.list, (item: number) => { 
              ListItem() { 
                Row() { 
                  Text('我要正常滚动__测试数据' + item).fontSize(20) 
                } 
              } 
            }, (i: string) => i) 
          }.width('100%').layoutWeight(1) // 设置组件占比权重 
        }.tabBar(this.TabHeader('消息')) 
         
        TabContent() { 
          Column() { 
          }.layoutWeight(1) // 设置组件占比权重 
        }.tabBar(this.TabHeader('云空间')) 
      } 
      .width('100%') 
      .layoutWeight(1) // 设置组件占比权重 
      .backgroundColor("#f1f2f6") 
      .flexGrow(1) 
      .onTouch((e) => { 
        // 添加一个触摸事件,让用户触摸键盘和输入框以外的区域时关闭输入框可以有更好的用户体验, 
        // IOS目前是这样实现的,但是当前版本系统接口不支持 
      }) 
 
      Row() { 
        TextInput({ text: this.text, placeholder: '底部输入框', controller: this.controller }) 
      } 
      .width('100%') 
      .height(50) 
      .backgroundColor("#dfe4ea") 
      .padding({ left: 20, right: 20 }) 
    }.width("100%") 
  } 
}

场景二:输入框在顶部时,保证页面不被遮挡

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

import window from '@ohos.window'; 
 
@Entry 
@Component 
struct Index { 
  @State screenHeight: number = 0; 
  @State text: string = '' 
  @State list: number[] = [] 
  controller: TextInputController = new TextInputController() 
 
  aboutToAppear() { 
    for (let index = 0; index < 20; index++) { 
      this.list.push(index) 
    } 
    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); 
      }) 
    }) 
  } 
 
  @Builder 
  TabHeader(text = '') { 
    Text(text).fontSize(30).fontColor(Color.Red).expandSafeArea([SafeAreaType.KEYBOARD]) 
  } 
 
  build() { 
    Row() { 
      Column() { 
        Row() { 
          TextInput({ text: this.text, placeholder: '顶部搜索框', controller: this.controller }) 
        } 
        .width('100%') 
        .height(50) 
        .backgroundColor(Color.Pink) 
        .padding({ left: 20, right: 20 }) 
 
        Tabs() { 
          TabContent() { 
            List({ space: 20 }) { 
              ForEach(this.list, (item: number) => { 
                ListItem() { 
                  Row() { 
                    Text('我要正常滚动__测试数据' + item).fontSize(20) 
                  } 
                } 
              }, (i: string) => i) 
            }.width('100%') 
          }.tabBar(this.TabHeader('消息')) 
 
          TabContent() { 
            Column() { 
            } 
          }.tabBar(this.TabHeader('云空间')) 
        } 
        .width('100%') 
        .backgroundColor("#f1f2f6") 
        .onTouch((e) => { 
          // 添加一个触摸事件,让用户触摸键盘和输入框以外的区域时关闭输入框,IOS目前是这样实现的,但是当前版本系统接口不支持 
        }) 
      } 
      .width('100%') 
    } 
    .width('100%').height(this.screenHeight) 
  } 
}

问题总结:

隐藏键盘功能暂未实现,目前系统接口不支持,接口支持后更新。

重绘方法获取页面高度不准确,具体原因暂未找到,后续定位后更新。

目前暂未实现沉浸式状态栏的场景,后续更新。

注明适配的版本信息

IDE:DevEco Studio 4.0.3.600

SDK:HarmoneyOS 4.0.10.11

分享
微博
QQ
微信
回复
2024-05-27 11:25:10
相关问题
如何控制软键盘弹出页面的遮挡?
1393浏览 • 1回复 待解决
如何判断软键盘是否弹出
652浏览 • 1回复 待解决
关于软键盘弹出遮挡问题
372浏览 • 1回复 待解决
鸿蒙软键盘弹出后,页面底部的按钮
2812浏览 • 0回复 待解决
API8 怎么隐藏软键盘
1278浏览 • 1回复 待解决
如何实现弹窗和软键盘的避让
528浏览 • 1回复 待解决
如何主动拉起软键盘,你知道吗?
849浏览 • 1回复 待解决
H5页面输入框自动获焦弹起软键盘
477浏览 • 1回复 待解决
Grid组件如何实现高度自适应
1363浏览 • 1回复 待解决
Web组件如何实现高度自适应
430浏览 • 1回复 待解决
页面上下拖动怎么隐藏键盘
510浏览 • 1回复 待解决
InnoDB为什么需要自适应的Hash索引?
1169浏览 • 1回复 待解决