HarmonyOS鸿蒙Next中弹窗的动画效果是如何实现的?如何使用动画API(如 Animator 和 AnimationOption)来实现显示和隐藏的动画效果?

HarmonyOS鸿蒙Next中弹窗的动画效果是如何实现的?如何使用动画API(如 Animator 和 AnimationOption)来实现显示和隐藏的动画效果? 弹窗的动画效果是如何实现的?如何使用HarmonyOS的动画API(如 AnimatorAnimationOption)来实现显示和隐藏的动画效果?

#HarmonyOS最强问答官#

3 回复

自定义弹窗的弹出动画和关闭动画:https://developer.huawei.com/consumer/cn/doc/harmonyos-faqs-V5/faqs-arkui-223-V5

import { BaseDialog } from './BaseDialog'
export class Test2Dialog extends BaseDialog<NumberParams> {
  private intervalId: number = -1
  createWrappedBuilder(): WrappedBuilder<[NumberParams]> {
    return wrapBuilder(buildTestDialog)
  }
  createParams(): NumberParams {
    return new NumberParams(this, 0, Visibility.Visible)
  }
  refresh() {
    if (this.intervalId != -1) {
      clearInterval(this.intervalId)
    }
    this.intervalId = setInterval(() => {
      this.params.value++
      this.update(this.params)
    }, 1000)
  }
  setClose(){
    this.params.showFlag = Visibility.Hidden;
  }
}

@Builder
function buildTestDialog(params: NumberParams) {
  TestDialogContent({ params: params })
}

/**
 * 弹窗UI
 */
@Component
struct TestDialogContent {
  @ObjectLink params: NumberParams
  build() {
    Column () {
      Text(this.params?.value?.toString())
        .fontSize(80)
      Row () {
        Button('CLOSE')
          .onClick(() => {
            this.params?.dialog.dismiss()
          })
      }
      .width('100%')
      .justifyContent(FlexAlign.SpaceAround)
    }
    .visibility(this.params?.showFlag)
    .width('100%')
    .height('30%')
    .backgroundColor(Color.White)
    .borderRadius(20)
    .justifyContent(FlexAlign.SpaceEvenly)
    .transition(TransitionEffect.asymmetric(
      TransitionEffect.move(TransitionEdge.BOTTOM),
      TransitionEffect.move(TransitionEdge.BOTTOM)).animation({ duration: 1000 }))
  }
}

/**
 * 传递给弹窗UI中的参数,参数变化可驱动UI变化
 */
@Observed
export class NumberParams {
  dialog: Test2Dialog
  value: number
  showFlag: Visibility
  constructor(dialog: Test2Dialog, value: number, showFlag: Visibility) {
    this.dialog = dialog
    this.value = value
    this.showFlag = showFlag
  }
}
import { ComponentContent, PromptAction, uiObserver } from '@kit.ArkUI'
import json from '@ohos.util.json'
import { JSON } from '@kit.ArkTS'
export abstract class BaseDialog<P extends Object> {
  protected uiContext: UIContext
  private weakUIContext: WeakRef<UIContext>
  private action: PromptAction
  private content: ComponentContent<P>
  protected isShowing = false
  private canceledOnTouchOutside = true // 点击弹窗外面是否关闭弹窗
  private canceledOnPressBack = true // 手势返回或者返回按钮关闭弹窗
  private alignment = DialogAlignment.Center
  protected params: P
  private currentPage: string
  private isOn = false
  private dismissByUser = false
  private maskColor: ResourceColor = $r('sys.color.mask_fourth')
  private showInSubWindow = false
  private isModel = true
  private transition?: TransitionEffect
  constructor(uiContext: UIContext) {
    this.currentPage = uiContext.getRouter().getState().path + uiContext.getRouter().getState().name
    this.weakUIContext = new WeakRef(uiContext)
    this.uiContext = this.weakUIContext.deref()!
    this.action = uiContext.getPromptAction()
    this.params = this.createParams()
    this.content = new ComponentContent(uiContext, this.createWrappedBuilder(), this.params)
  }
  setCanceledOnTouchOutside(cancel: boolean) {
    this.canceledOnTouchOutside = cancel
    return this
  }
  setCanceledOnPressBack(cancel: boolean) {
    this.canceledOnPressBack = cancel
    return this
  }
  setAlignment(alignment: DialogAlignment) {
    this.alignment = alignment
    return this
  }
  setMaskColor(color: ResourceColor) {
    this.maskColor = color
    return this
  }
  setShowInSubWindow(inSub: boolean) {
    this.showInSubWindow = inSub
    return this
  }
  setTransition(transition: TransitionEffect) {
    this.transition = transition
  }
  setModel(model: boolean) {
    this.isModel = model
    return this
  }
  show(params?: P) {
    if (!this.isShowing) {
      this._show()
    }
    if (params) {
      this.update(params)
    }
  }
  private routerPageUpdate(info: RouterPageInfo) {
    if (this.currentPage !== info.name) {
      return
    }
    if (info.state === uiObserver.RouterPageState.ON_PAGE_SHOW) {
      if (!this.dismissByUser) {
        this.show()
      }
    } else if (info.state === uiObserver.RouterPageState.ON_PAGE_HIDE) {
      this._dismiss() // 在弹窗上打开了新的页面,自动关闭弹窗,等下次再回到弹窗页面时再次打开弹窗
    }
  }
  update(params: P) {
    if (!this.isShowing) {
      return
    }
    this.params = params
    this.content.update(params)
  }
  dismiss() {
    this.setClose()
    setTimeout(() => {
      this.dismissByUser = true
      this.uiContext.getUIObserver().off("routerPageUpdate")
      this.isOn = false
      this._dismiss()
    }, 1000)
  }
  private _show() {
    this.dismissByUser = false
    this.isShowing = true
    if (!this.isOn) {
      this.isOn = true
      this.uiContext.getUIObserver().on("routerPageUpdate", (info) => {
        this.routerPageUpdate(info)
      })
    }
    this.action.openCustomDialog(this.content, {
      alignment: this.alignment,
      isModal: this.isModel,
      maskColor: this.maskColor,
      showInSubWindow: this.showInSubWindow,
      transition: this.transition,
      onWillDismiss: (dialogAction: DismissDialogAction) => {
        console.log(`dialog_action : ${json.stringify(dialogAction)}`)
        if (dialogAction.reason === DismissReason.PRESS_BACK && this.canceledOnPressBack) {
          this.dismiss()
        }
        if (dialogAction.reason === DismissReason.TOUCH_OUTSIDE && this.canceledOnTouchOutside) {
          this.dismiss()
        }
      },
      onDidAppear: () => {
        this.isShowing = true
      },
      onDidDisappear: () => {
        this.isShowing = false
      }
    })
  }
  private _dismiss() {
    try {
      this.isShowing = false
      this.action.closeCustomDialog(this.content)
    } catch (error) {
      console.error(`OpenCustomDialog message : ${error}`);
    }
  }
  abstract createWrappedBuilder(): WrappedBuilder<[P]>
  abstract createParams(): P
  abstract setClose(): void
}

更多关于HarmonyOS鸿蒙Next中弹窗的动画效果是如何实现的?如何使用动画API(如 Animator 和 AnimationOption)来实现显示和隐藏的动画效果?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,弹窗的动画效果主要通过AnimatorAnimationOption来实现。Animator是鸿蒙系统中用于处理动画的核心类,而AnimationOption则用于配置动画的各个参数,如持续时间、延迟、插值器等。

  1. Animator: Animator类用于创建和管理动画。你可以通过继承Animator或使用其子类(如PropertyAnimator)来定义动画行为。Animator提供了诸如start()pause()resume()stop()等方法来控制动画的生命周期。

  2. AnimationOption: AnimationOption类用于配置动画的细节。你可以通过AnimationOption设置动画的持续时间、延迟、重复次数、插值器等。例如,AnimationOption.setDuration(500)可以将动画持续时间设置为500毫秒。

  3. 实现显示和隐藏的动画效果:

    • 显示动画: 通过Animator创建一个动画,设置目标属性(如透明度、位置等)从初始值到目标值的变化。使用AnimationOption配置动画参数,然后调用start()方法启动动画。
    • 隐藏动画: 类似于显示动画,但目标属性是从当前值返回到初始值。同样使用AnimationOption配置动画参数,并调用start()方法启动动画。

通过组合AnimatorAnimationOption,你可以实现复杂的弹窗动画效果,如淡入淡出、滑动、缩放等。

在HarmonyOS鸿蒙Next中,弹窗的动画效果可以通过AnimatorAnimationOption实现。首先,使用Animator定义动画的属性变化,如透明度、位置等。然后,通过AnimationOption设置动画的持续时间、延迟、重复次数等参数。在显示弹窗时,调用start()方法启动动画;在隐藏时,使用reverse()或重新定义动画来实现反向效果。例如,可以通过改变alpha值实现淡入淡出效果。

回到顶部