在HarmonyOS NEXT开发中希望监听键盘高度,在键盘弹出后组件上移,键盘收起后组件恢复,并且可以自行控制避让高度?

在HarmonyOS NEXT开发中希望监听键盘高度,在键盘弹出后组件上移,键盘收起后组件恢复,并且可以自行控制避让高度?

阅读 793
avatarAI BotBETA

在HarmonyOS NEXT中可以通过窗口事件监听实现键盘高度监测,具体实现方案如下:

@Entry
@Component
struct KeyboardAvoidView {
  @State keyboardHeight: number = 0
  @State isKeyboardShow: boolean = false

  // 自定义避让高度(可动态调整)
  @Prop customOffset: number = 20 

  onWindowStageEvent(event: window.WindowStageEvent) {
    if (event.type === window.WindowStageEventType.ACTIVE) {
      const display = window.getTopWindow(this.context).getWindowProperties().display
      const screenHeight = display.height
      const windowHeight = display.windowHeight
      
      // 计算键盘高度
      const currentKeyboardHeight = screenHeight - windowHeight
      
      if (currentKeyboardHeight > 0) {
        this.isKeyboardShow = true
        // 设置自定义避让高度(实际键盘高度 + 自定义偏移)
        this.keyboardHeight = currentKeyboardHeight + this.customOffset
      } else {
        this.isKeyboardShow = false
        this.keyboardHeight = 0
      }
    }
  }

  build() {
    Column() {
      // 需要避让的内容区域
      TextInput({ placeholder: '输入框' })
        .width('90%')
        .margin({ bottom: 20 })
    }
    .onWindowStageEvent(this.onWindowStageEvent.bind(this))
    .margin({ bottom: this.keyboardHeight })
    .animation({ duration: 100, curve: Curve.Ease })
  }
}

关键实现说明:

  1. 使用onWindowStageEvent监听窗口变化事件
  2. 通过window.getTopWindow获取窗口属性
  3. 计算屏幕高度与窗口高度的差值得到键盘高度
  4. 通过@State变量驱动UI更新
  5. 添加动画效果使过渡更流畅
  6. customOffset参数允许自定义额外避让高度

扩展控制方案:

  • 可通过修改customOffset动态调整避让距离
  • 使用isKeyboardShow状态控制其他交互逻辑
  • 结合Scroll组件实现更复杂的滚动避让逻辑
  • 支持不同设备屏幕方向适配处理

注意:实际开发中需要根据不同设备做像素密度转换,建议使用vp2px进行单位转换保证显示一致性。

1 个回答

你可参考如下示例:

//WebViewComponent.ets 
import { IAdjustOffsetParams } from '../viewmodel/IAdjustOffsetParams' 
// WebViewNode.ets 
import web_webview from '@ohos.web.webview' 
import { UIContext } from '@ohos.ArkUI.UIContext' 
import { BuilderNode, FrameNode, NodeController } from '@ohos.ArkUI.node' 
import WebViewComponent from '../view/WebViewComponent' 
import { WebBuilderParmas } from '../viewmodel/WebBuilderParmas' 
import { WebViewNodeUpdateParams } from '../viewmodel/WebViewNodeUpdateParams' 
 
@Component 
export default struct WebViewComponent { 
  @Prop @Watch('onAdjustOffsetChange') adjustOffset: IAdjustOffsetParams | null 
 
  onAdjustOffsetChange() { 
    if(this.adjustOffset) { 
      console.info(`TAG adjustOffset changed: x=${this.adjustOffset.x} y=${this.adjustOffset.y}`) 
    } else { 
      console.info(`TAG adjustOffset is null !`) 
    } 
  } 
 
  build() { 
    Row(){ 
      Text('Hello World') 
        .fontSize(20) 
        .fontColor(Color.Blue) 
    } 
    .backgroundColor(Color.White) 
  } 
} 
 
 
@Builder 
function webBuilder(params: WebBuilderParmas) { 
  Column() { 
    WebViewComponent({ 
      adjustOffset: params.adjustOffset 
    }) 
  } 
} 
 
class MyNodeController extends NodeController { 
  private rootNode: BuilderNode<[WebBuilderParmas]> | null = null; 
  private wrapBuilder: WrappedBuilder<[WebBuilderParmas]> = wrapBuilder(webBuilder); 
 
  makeNode(uiContext: UIContext): FrameNode | null { 
    if (this.rootNode === null) { 
      this.rootNode = new BuilderNode(uiContext); 
      this.rootNode.build(this.wrapBuilder, { text: "This is a Text" }) 
    } 
    return this.rootNode.getFrameNode(); 
  } 
 
 
  updateNode(updateParams: WebViewNodeUpdateParams) { 
    const params: WebBuilderParmas = { 
      adjustOffset : updateParams.adjustOffset 
    } 
    console.info(`TAG updateNode: ${JSON.stringify(params)}`) 
 
    this.rootNode?.update(params) 
  } 
} 
 
@Entry 
@Component 
struct MainPage { 
  controller: web_webview.WebviewController = new web_webview.WebviewController() 
  private myNodeController: MyNodeController = new MyNodeController(); 
  private currX: number = 0; 
  private currY: number = 0; 
 
  build() { 
    Column() { 
      NodeContainer(this.myNodeController) 
 
      Button('click to update') 
        .onClick(() => { 
          this.currX += 100; 
          this.currY += 100; 
          const updateParams : WebViewNodeUpdateParams = { 
            adjustOffset: { 
              x: this.currX, 
              y: this.currY 
            } 
          } 
          this.myNodeController.updateNode(updateParams) 
        }) 
 
    } 
  } 
} 
涉及的参数: 
//IAdjustOffsetParams.ets 
export interface IAdjustOffsetParams { 
  x?: number; 
  y?: number; 
} 
 
//WebBuilderParmas.ets 
 
export interface WebBuilderParmas { 
  adjustOffset: IAdjustOffsetParams; 
} 
 
// WebViewNodeUpdateParams.ets 
 
export interface WebViewNodeUpdateParams { 
  adjustOffset: IAdjustOffsetParams; 
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进