HarmonyOS鸿蒙Next中半模态弹窗键盘收起ui问题

HarmonyOS鸿蒙Next中半模态弹窗键盘收起ui问题 运行如下demo, 1.点击测试 2.点击请输入,键盘唤起 3.点击上方灰色区域,返回主page 预期:整个dialog页往下拉,然后页面消失,回到主page 结果:pop后上方灰色会往下拉,不会拉到低页面消失,而是拉到如图所示,卡顿一下,然后消失回到主界面。

cke_511.png 图片

最小demo如下使用navDestination唤起弹窗时,弹窗内有输入框,设置键盘避让为KeyboardAvoidMode.RESIZE,当点击灰色区域执行this.pageStack.pop()时,动画会出现bug

import { KeyboardAvoidMode,  } from "@kit.ArkUI";
@Entry
@Component
export struct textpage {
  @Provide('navPathStack') pageStack: NavPathStack = new NavPathStack()
  aboutToAppear(): void {
    this.getUIContext().setKeyboardAvoidMode(KeyboardAvoidMode.RESIZE)
  }
  @Builder
  PagesMap(name:string){
    if(name =='Test'){
      Test()
    }
  }
  build() {
    Navigation(this.pageStack) {
      Column() {
        Button('测试')
          .onClick(()=>{
            this.pageStack.pushPathByName('Test','')
          })
      }
    }
    .mode(NavigationMode.Stack)
    .navDestination(this.PagesMap)
  }

}


@Component
export struct Test {
  @Consume('navPathStack') pageStack: NavPathStack;

  build() {
    NavDestination() {
      Column()
        .width('100%')
        .height('40%')
        .backgroundColor('rgba(0,0,0,0.2)')
        .onClick(()=>{
          this.pageStack.pop()
        })

      TextArea({ placeholder: '请输入' })
      Column()
        .width('100%')
        .height(200)
        .backgroundColor(Color.White)
    }
    .hideTitleBar(true)
    .mode(NavDestinationMode.DIALOG)
  }
}

更多关于HarmonyOS鸿蒙Next中半模态弹窗键盘收起ui问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

9 回复

【背景知识】

KeyboardAvoidMode:配置键盘弹出时页面的避让模式。其中OFFSET上抬模式,RESIZE压缩模式。

visibility:控制组件的显示或隐藏。当未设置visibility时,组件默认为显示。

【解决方案】

使用KeyboardAvoidMode.OFFSET可解决页面下拉卡顿问题,但会遮挡TextArea下方内容;因此在NavDestination上添加visibility属性,控制NavDestination的显示或隐藏,解决卡顿问题。

import { KeyboardAvoidMode } from '@kit.ArkUI';

@Entry
@Component
export struct textpage {
  @Provide('navPathStack') pageStack: NavPathStack = new NavPathStack()

  aboutToAppear(): void {
    this.getUIContext().setKeyboardAvoidMode(KeyboardAvoidMode.OFFSET)
  }

  @Builder
  PagesMap(name: string) {
    if (name == 'Test') {
      Test()
    }
  }

  build() {
    Navigation(this.pageStack) {
      Column() {
        Button('测试')
          .onClick(() => {
            this.pageStack.pushPathByName('Test', '')
          })
      }
    }
    .mode(NavigationMode.Stack)
    .navDestination(this.PagesMap)
  }
}


@Component
export struct Test {
  @Consume('navPathStack') pageStack: NavPathStack;
  @State isVisibility: boolean = false

  build() {
    NavDestination() {
      Column()
        .width('100%')
        .height('40%')
        .backgroundColor('rgba(0,0,0,0.2)')
        .onClick(() => {
          this.isVisibility = !this.isVisibility
          this.pageStack.pop()
        })

      TextArea({ placeholder: '请输入' })
      Text('I can see the bottom of the page')
        .width('100%')
        .textAlign(TextAlign.Center)
        .backgroundColor('rgb(179,217,235)')
        .layoutWeight(1)
    }
    .hideTitleBar(true)
    .visibility(this.isVisibility ? Visibility.Hidden : Visibility.Visible)
    .mode(NavDestinationMode.DIALOG)
  }
}

更多关于HarmonyOS鸿蒙Next中半模态弹窗键盘收起ui问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


背景知识:

楼主,可以将 KeyboardAvoidMode.RESIZE -> KeyboardAvoidMode.OFFSET 就可以解决灰色块挂住后消失问题。

问题解决:

代码:

@Entry
@Component
struct NavigationDialogPage {
    @State message: string = 'Hello World';
    @Provide('navPathStack') pageStack: NavPathStack = new NavPathStack()


    aboutToAppear(): void {
      //修改  KeyboardAvoidMode.OFFSET 就不会出现挂住问题了
        this.getUIContext().setKeyboardAvoidMode(KeyboardAvoidMode.OFFSET )
    }

    @Builder
    PagesMap(name: string) {
        if (name == 'Test') {
            Test()
        }
    }

    build() {
        Navigation(this.pageStack) {
            Button("测试弹窗")
                .fontSize(20)
                .fontColor(Color.White)
                .fontWeight(FontWeight.Bold)
                .onClick(() => {
                    this.pageStack.pushPathByName('Test', '')
                })
        }
        .width("100%")
        .height("100%")
        .mode(NavigationMode.Stack)
        .navDestination(this.PagesMap)
    }
}

@Component
export struct Test {
    @Consume('navPathStack') pageStack: NavPathStack

    build() {
        NavDestination() {
            Column()
                .width('100%')
                .height('40%')
                .backgroundColor('rgba(0,0,0,0.2)')
                .onClick(() => {
                    this.pageStack.pop()
                })

            TextArea({ placeholder: '请输入' })
            Column()
                .width('100%')
                .height(200)
                .backgroundColor(Color.White)
        }
        .hideTitleBar(true)
        .mode(NavDestinationMode.DIALOG)
    }
}

真机演示:

cke_47576.gif

期待HarmonyOS能在未来带来更多创新的技术和理念。

业务中下方内容不能被覆盖的。

找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17

可能是因为如下问题导致

动画卡顿原因:键盘收起与弹窗关闭动画未同步,RESIZE模式下的布局重计算导致动画帧丢失

层级冲突:键盘窗口与弹窗窗口的动画优先级未正确协调

生命周期顺序:pop操作触发时未优先处理键盘状态

可以尝试以下方案

1.优化键盘状态同步:

onClick(async () => {

// 先隐藏键盘

const inputController = TextAreaController.getDefaultInstance();

await inputController.hideSoftKeyboard();

// 延迟确保键盘动画完成

setTimeout(() => {

this.pageStack.pop();

}, 100);

})

2.调整避让模式组合:

aboutToAppear(): void {

// 采用组合避让策略

this.getUIContext().setKeyboardAvoidMode(

KeyboardAvoidMode.OFFSET | KeyboardAvoidMode.RESIZE

);

}

3.添加动画过渡补偿:

NavDestination() {

Column()

.transition({ type: TransitionType.All, duration: 300 })

// ...其他样式

}

.mode(NavDestinationMode.DIALOG)

我提问题的时候,采用的方案就是1,但是我觉得加延迟的方案有点笨。

在HarmonyOS Next中,半模态弹窗键盘收起时UI问题通常涉及弹窗高度调整或布局重绘。可通过监听键盘状态变化,使用avoidKeyboard属性自动适配布局。若使用ArkTS开发,检查弹窗组件的onKeyboardHide回调,确保UI组件尺寸和位置正确更新。避免硬编码布局参数,采用弹性布局适配不同场景。

这是一个已知的键盘避让与半模态弹窗动画的兼容性问题。当使用KeyboardAvoidMode.RESIZE模式时,系统会调整页面布局以适应键盘高度,但在执行pop操作时,动画系统未能正确处理键盘收起过程中的布局变化。

问题核心在于:键盘避让导致的布局调整与弹窗关闭动画产生了时序冲突。当点击灰色区域触发pop时,系统需要同时处理键盘收起和弹窗关闭两个动画,但RESIZE模式下的布局变化干扰了弹窗的平滑关闭动画。

建议的临时解决方案:

  1. 在pop操作前手动关闭键盘
  2. 使用KeyboardAvoidMode.OFF模式,改用padding或margin手动处理键盘遮挡
  3. 添加短暂延迟确保键盘完全收起后再执行pop

这个问题已在HarmonyOS Next的后续版本中得到修复,建议关注官方更新日志获取修复版本信息。

回到顶部