HarmonyOS 鸿蒙Next 自定义弹窗怎么设置从上到下的弹窗动画
HarmonyOS 鸿蒙Next 自定义弹窗怎么设置从上到下的弹窗动画 CustomDialogController设置“灰色阴影”从顶部到底部的弹出效果,关闭时相反
请参考demo
import { Test1Dialog } from './Test1Dialog'
@Entry
@Component
struct Index {
build() {
Column() {
Button('弹窗1')
.onClick(() => {
const dialog1 = new Test1Dialog(this.getUIContext())
dialog1.setAlignment(DialogAlignment.Bottom)
// 方式1:给Dialog设置动画
dialog1.setTransition(TransitionEffect.asymmetric(TransitionEffect.move(TransitionEdge.BOTTOM),
TransitionEffect.move(TransitionEdge.BOTTOM)).animation({ duration: 1000 }))
dialog1.show()
dialog1.refresh()
})
}
.justifyContent(FlexAlign.Center)
.height('100%')
.width('100%')
}
}
import { ComponentContent, PromptAction, uiObserver } from '@kit.ArkUI'
import json from '@ohos.util.json'
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.dismissByUser = true
this.uiContext.getUIObserver().off("routerPageUpdate")
this.isOn = false
this._dismiss()
}
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
}
import { BaseDialog } from './BaseDialog';
export class Test1Dialog extends BaseDialog<NumberParams> {
private intervalId: number = -1
createWrappedBuilder(): WrappedBuilder<[NumberParams]> {
return wrapBuilder(buildTestDialog)
}
createParams(): NumberParams {
return new NumberParams(this, 0)
}
refresh() {
if (this.intervalId != -1) {
clearInterval(this.intervalId)
}
this.intervalId = setInterval(() => {
this.params.value++
this.update(this.params)
}, 1000)
}
}
@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)
}
.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: Test1Dialog
value: number
constructor(dialog: Test1Dialog, value: number) {
this.dialog = dialog
this.value = value
}
}
更多关于HarmonyOS 鸿蒙Next 自定义弹窗怎么设置从上到下的弹窗动画的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
这样实现,背景遮罩如果不是纯透明,遮罩也会跟着动画;
请问如何实现只有弹窗动画,遮罩不变呢?
在HarmonyOS鸿蒙Next系统中,设置自定义弹窗从上到下的动画效果,可以通过以下步骤实现:
-
定义动画资源: 首先,在
res/animation
目录下定义两个动画资源文件,一个用于描述弹窗从顶部进入的动画(例如slide_in_from_top.xml
),另一个用于描述弹窗退出时到顶部的动画(例如slide_out_to_top.xml
)。这两个文件分别定义动画的起始和结束位置、持续时间等属性。 -
应用动画到弹窗: 在创建弹窗的代码中,通过弹窗的
setEnterAnimation
和setExitAnimation
方法,将上述定义的动画资源应用到弹窗上。这样,当弹窗显示或隐藏时,就会按照定义的动画效果进行。 -
弹窗显示与隐藏: 在需要显示弹窗的地方调用弹窗的
show
方法,在需要隐藏弹窗的地方调用hide
方法。此时,弹窗将按照定义的动画效果进行显示和隐藏。
如果上述步骤正确实施,弹窗应该能够按照从上到下的动画效果进行显示和隐藏。如果问题依旧没法解决请联系官网客服,官网地址是。