场景描述
透明页面也可以叫做弹窗页面,实际开发场景中经常有一个页面覆盖在另一个页面上的效果,例如:评论弹窗页面、广告弹窗页面等。
场景:评论弹窗页面
功能点:
- 弹窗页面拉起。
- 评论页面状态持久化保存。
- 带参页面拉起。
方案一:使用router+subWindow实现
router路由无法更改页面模式,所以无法直接实现透明页面,需要借助拉起子窗口的方案实现透明页面的效果。思路如下:
-
获取窗口实例。
-
拉起一个子窗口并加载对应页面。
-
设置子窗口背景透明。
-
定义子窗口的关闭方案。
核心代码
在Ability中获取windowStage实例。
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
windowStage.loadContent('pages/Index', (err) => {
// 这里需要注意为了确保windowStage实例获取成功,我们最好在loadContent回调中回去,能保证页面加载成功的时候一定能讲windowStage实例存到AppStorage对象中
AppStorage.setOrCreate("windowStage", windowStage);
});
}
创建一个子窗口作为页面载体,并加载RouterOpacityPage页面。
private windowClass: window.WindowStage | null = null
aboutToAppear(): void {
this.windowClass = AppStorage.get("windowStage") as window.WindowStage;
}
build() {
...
Button("使用router路由")
.onClick(() => {
this.windowClass?.createSubWindow("routerOpacityPage", (err, win) => {
win.setUIContent('pages/RouterOpacityPage');
win.showWindow();
})
})
...
}
加载页面后,这时候出现的新页面发现并不是透明的,那么我们把页面跟容器设置背景颜色为透明,也没有效果,根因是窗口默认是不透明的,需要设置窗口背景色。
@Entry
@Component
struct RouterOpacityPage {
aboutToAppear(): void {
// 设置当前窗口背景透明
window.findWindow("routerOpacityPage").setWindowBackgroundColor("#00000000");
}
build() {
...
}
}
需要注意的是,子窗口无法与主窗口事件交互,并且默认的手势返回也无法销毁,所以需要自己监听页面的返回手势来销毁子窗口来实现回到原页面的效果。
onBackPress(): boolean | void {
// 这里解释下为什么需要用显示动画,因为窗口消失的时候无法对窗口添加动画,在转场动画中动画结束回调不生效,所以只能通过显示动画来控制组件显影然后在结束回调同销毁窗口
animateTo({
duration: 300, onFinish: () => {
window.findWindow("routerOpacityPage").destroyWindow().then((res) => {
console.log("destroyWindow success");
}).catch(() => {
console.log("destroyWindow fail");
})
}
}, () => {
this.opacityValue = 0;
})
return true;
}
RouterOpacityPage 完整代码如下:
import { window } from '@kit.ArkUI'
@Entry
@Component
struct RouterOpacityPage {
@State opacityValue: number = 1;
aboutToAppear(): void {
// 设置当前窗口背景透明
window.findWindow("routerOpacityPage").setWindowBackgroundColor("#00000000");
}
onBackPress(): boolean | void {
// 这里解释下为什么需要用显示动画,因为窗口消失的时候无法对窗口添加动画,在转场动画中动画结束回调不生效,所以只能通过显示动画来控制组件显影然后在结束回调同销毁窗口
animateTo({
duration: 300, onFinish: () => {
window.findWindow("routerOpacityPage").destroyWindo