HarmonyOS 鸿蒙Next 如何让弹窗先离屏加载好后隔一段时间再挪回屏幕

发布于 1周前 作者 ionicwang 最后一次编辑是 5天前 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 如何让弹窗先离屏加载好后隔一段时间再挪回屏幕

如何让弹窗先离屏加载好后隔一段固定时间后再挪回屏幕展示,离屏期间不影响正在展示页面的交互

3 回复

可以参考下面这个例子,使用buildNode预载组件,然后传递到弹框中由 ContentSlot(this.content) 展示,延时显示弹框用setTimeout去执行this.controller.open()

参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V13/js-apis-arkui-buildernode-V13#build12

预载页面:

interface ParamsInterface {
  text: string;
  func: Function;
  node: FrameNode
}

@Builder
function buildText(params: ParamsInterface) {
  Column() {
    Button(params.text)
      .fontSize(50)
      .fontWeight(FontWeight.Bold)
      .margin({ bottom: 36 })
      .onClick( () => {
      })
    Image('https://i-blog.csdnimg.cn/blog_migrate/36e0a797236b28f7b89b630b421f7dc9.jpeg')
      .width(100)
      .height(100)
  }
}


@Entry
@Component
struct Index {
  @State message: string = "HELLO"
  private content: NodeContent = new NodeContent();
  @State node?: FrameNode = new FrameNode(this.getUIContext());
  @State visible: Visibility = Visibility.Hidden
  build() {
    Row() {
      Column() {
        Button('addBuilderNode')
          .onClick(() => {
            let buildNode = new BuilderNode<[ParamsInterface]>(this.getUIContext());
            buildNode.build(wrapBuilder<[ParamsInterface]>(buildText), {
              text: this.message, func: () => {
                return "FUNCTION"
              }
            }, { nestingBuilderSupported: true });
            console.debug("buildNode build finish")
            this.node = buildNode.getFrameNode()!;
            this.visible = Visibility.Visible
            this.content.addFrameNode(buildNode.getFrameNode());
          })
        MyCustomDialog({node: this.node,
          visible: this.visible})
        // ContentSlot(this.content)
      }
      .id("column")
      .width('100%')
      .height('100%')
    }
    .height('100%')
  }
}

弹窗组件

import {  inspector } from "@kit.ArkUI";
import { FrameNode, NodeContent } from '@kit.ArkUI';

// 弹窗交互
@CustomDialog
export struct CustomDialogExample {
  private content: NodeContent = new NodeContent();
  controller?: CustomDialogController
  node?: FrameNode;
  isAutoCancel: boolean = true;
  listener:inspector.ComponentObserver = inspector.createComponentObserver('Column_ID')
  aboutToAppear() {
    this.content.addFrameNode(this.node!);
    console.debug(" build  aboutToAppear")
    let onLayoutComplete:()=>void=():void=>{
      console.debug("LayoutComplete build finish")
      // do something here
    }
    let onDrawComplete:()=>void=():void=>{
      console.debug("DrawComplete build finish")
      // do something here
    }
    let FuncLayout = onLayoutComplete // bind current js instance
    let FuncDraw = onDrawComplete // bind current js instance

    this.listener.on('layout', FuncLayout)
    this.listener.on('draw', FuncDraw)
  }
  build() {
    Column() {
      Row() {
        Text('Hello World')
        .fontSize(20)
      }
      .padding(8)
      .backgroundColor('#FFFFFF')
      .height(200)
        .margin({ bottom: -5 })
        .width('100%')
      ContentSlot(this.content)
    }
    .justifyContent(FlexAlign.End)
    .width('100%')
    .height('100%')
    .margin({
      bottom: -15
    })
    .onClick(() => {
      console.log('dialogClick')
      if (this.isAutoCancel) {
        this.cancel();
      }
    })
    // .visibility(this.visible)
    .transition(TransitionEffect.asymmetric(
      TransitionEffect.move(TransitionEdge.BOTTOM).animation({ duration: 300 }),
      TransitionEffect.move(TransitionEdge.BOTTOM).animation({ duration: 300 }))
    )
    .id('Column_ID')
  }

  cancel() {
    // this.visible = Visibility.Hidden
  }
}

@Component
export struct MyCustomDialog {
  @Watch('onChange') @Link visible: Visibility
  @Link node: FrameNode;
  private controller = new CustomDialogController({
    builder: CustomDialogExample({node:this.node}),
    customStyle: true
  })
  aboutToAppear() {
    console.debug("aboutToAppear start")
  }
  onChange() {
    if (this.visible === Visibility.Visible) {
      this.controller = new CustomDialogController({
        builder: CustomDialogExample({node:this.node}),
        customStyle: true
      })
      setTimeout(() => {
        this.controller.open()
        console.debug("controller open")
      }, 3000);
    } else {
      console.log('syt onchange close window');
      this.controller.close()
    }
  }
  build() {
  }
}

更多关于HarmonyOS 鸿蒙Next 如何让弹窗先离屏加载好后隔一段时间再挪回屏幕的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


BuilderNode 提前Build?没在屏幕上,但是UI提前加载了

在HarmonyOS鸿蒙Next系统中,实现弹窗先离屏加载好再隔一段时间挪回屏幕的效果,可以通过自定义动画和定时器来完成。具体步骤如下:

  1. 创建弹窗:首先,使用系统提供的弹窗组件或者自定义弹窗视图。确保弹窗内容已正确加载。

  2. 设置初始位置:在弹窗创建时,将其位置设置在屏幕外(如屏幕下方或左侧,确保不在可视区域内)。

  3. 加载动画资源:为弹窗创建两个动画资源,一个是初始加载时的隐藏动画(保持离屏状态),另一个是显示动画(将弹窗从离屏位置移动到屏幕内)。

  4. 应用动画:在弹窗加载完成后,立即应用隐藏动画(实际上此时弹窗已不在屏幕内,这一步是为了逻辑上的完整性)。然后,通过定时器(如HandlerpostDelayed方法)设置一个延迟,在延迟结束后应用显示动画。

  5. 显示弹窗:定时器到期后,触发显示动画,将弹窗从离屏位置平滑地移动到屏幕内的目标位置。

示例代码框架(省略具体实现细节):

// 伪代码示例,具体实现需根据鸿蒙开发文档调整
弹窗.setPosition(离屏位置);
弹窗.show();
动画管理器.playHiddenAnimation(弹窗);
Handler().postDelayed({
    动画管理器.playShowAnimation(弹窗, 目标位置);
}, 延迟时间);

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部