HarmonyOS 鸿蒙Next中如何定位键盘弹出后原UI布局错乱问题

HarmonyOS 鸿蒙Next中如何定位键盘弹出后原UI布局错乱问题

【问题现象】

在键盘弹出时,用户界面布局出现错乱现象,比如键盘遮挡输入框、Tab被键盘顶起、导航栏被顶出屏幕等问题。

效果如下:

上图为初始状态,下图为错误的场景:

点击放大

点击放大

【背景知识】

  • 软键盘布局适配场景介绍,键盘避让机制。 参考链接:键盘布局适配
  • layoutWeight:组件在父组件剩余空间的布局权重。 参考链接:layoutWeight
  • expandSafeArea:控制组件扩展其安全区域。 参考链接:expandSafeArea

【定位思路】

键盘的避让模式 KeyboardAvoidMode 默认为OFFSET,此时键盘的避让效果为整体页面被顶起,符合问题现象。

【解决方案】

1. 使用RESIZE键盘避让模式

设置KeyboardAvoidMode值为RESIZE,此时页面中设置百分比宽高的组件会跟随页面压缩,直接设置宽高的组件会按设置的固定大小布局。

示例中List 容器使用layoutWeight(1),layoutWeight(number) 属性作用为组件在父组件主轴方向的布局权重,即占父组件容器在主轴方向上剩余区域的多少,自适应占满父组件剩余空间。此时键盘弹出时List组件高度会被压缩,其他组件的高度不变。而在RESIZE模式下,expandSafeArea设置不生效。

效果如下:最下方“Red Square Below”被键盘顶起,List组件高度被压缩。

点击放大

2. 键盘弹出时控制组件是否避让

当不需要被顶起的组件被键盘顶起时,可通过expandSafeArea使该组件不避让键盘。需要注意,在KeyboardAvoidMode.RESIZE模式下,expandSafeArea属性不生效。

expandSafeArea意为扩大安全区域,KEYBOARD事件下,扩展TOP、BOTTOM区域,即该组件可以渲染到键盘的上下区域,此时该组件不避让键盘。

代码示例如下:

Blank() { // Blank为任意UI组件
}.expandSafeArea([SafeAreaType.KEYBOARD], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM]) // 意为该组件可以渲染到键盘遮盖的区域

效果如下:

上图中,底部的BottomTextArea未设置键盘避让,因此输入时仅该组件被顶起,其余组件未被顶起。

下图中,List设置了键盘避让,此时最下方的TextInput组件输入时,该输入组件被键盘遮挡。

点击放大

3. 通过监听键盘高度或安全区域高度变化,手动处理UI布局

手动处理UI布局时,要注意容器组件的高度是否为固定高度,推荐使用layoutWeight属性自适应容器或组件高度。

当页面释放时,要注意关闭键盘事件监听。

代码示例如下:

aboutToAppear(): void {
 this.setKeyboardHandler();
}
aboutToDisappear(): void {
  // 关闭键盘高度监听,避免内存泄露
  this.keyboardListenerWindow && this.keyboardListenerWindow.off('keyboardHeightChange');
}
setKeyboardHandler() {
  window.getLastWindow(getContext(this)).then(currentWindow => {
    this.keyboardListenerWindow = currentWindow;
    currentWindow.on('keyboardHeightChange', (height:number) => {
      this.keyboardHeight = px2vp(height);
      // 后续根据键盘弹出的高度,自行计算组件布局。
    })
  })
}

效果如下:

图一:Bottom TextArea输入时,最底部“Red Square Below”被顶起。

图二:列表中奇数位输入框输入时,顶起位置为底部“Red Square Above”。

图三:列表中偶数位输入框输入时,顶起位置为List底部,即List下方“Red Square Above”被键盘遮挡。

点击放大

点击放大

点击放大

【总结】

  • KeyboardAvoidMode.RESIZE模式下,expandSafeArea设置将不起作用。
  • 容器组件推荐使用百分比宽高度设置,如 width(‘100%’),或使用layoutWeight(1)。
  • 列表类容器内的子组件若使用expandSafeArea,需要进行嵌套。因此,不推荐对列表容器内的子组件使用此属性。
  • 使用各种监听时,务必在退出页面前取消监听,以避免潜在的内存泄漏。
  • 在自定义页面顶起高度时,可以在容器最底部使用Blank组件,并根据需要被顶起的高度结合animateTo显式动画设置Blank组件的高度,以实现页面顶起效果。

更多关于HarmonyOS 鸿蒙Next中如何定位键盘弹出后原UI布局错乱问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS 鸿蒙Next中如何定位键盘弹出后原UI布局错乱问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


定位键盘弹出后原UI布局错乱问题,可通过以下方法解决:

1. 使用RESIZE键盘避让模式

设置KeyboardAvoidModeRESIZE,页面中设置百分比宽高的组件会跟随页面压缩,直接设置宽高的组件保持固定大小。List容器使用layoutWeight(1)时,键盘弹出时List组件高度会被压缩,其他组件高度不变。

2. 控制组件是否避让键盘

通过expandSafeArea使组件不避让键盘。在KEYBOARD事件下,扩展TOPBOTTOM区域,组件可以渲染到键盘的上下区域,此时该组件不避让键盘。注意:在KeyboardAvoidMode.RESIZE模式下,expandSafeArea不生效。

3. 监听键盘高度或安全区域高度变化,手动处理UI布局

监听键盘高度变化,手动调整UI布局。推荐使用layoutWeight属性自适应容器或组件高度。页面释放时,关闭键盘事件监听。

总结

  • RESIZE模式下expandSafeArea不生效。
  • 推荐使用百分比宽高或layoutWeight
  • 列表容器内子组件不推荐使用expandSafeArea
  • 退出页面前取消监听,避免内存泄漏。
  • 可使用Blank组件结合animateTo显式动画实现页面顶起效果。
回到顶部