09窗口管理
小窗(悬浮窗)
窗口管理
入库类中:创建窗口和销毁窗口的核心代码。
设计小窗参数接口
呈现小窗口时需要指定小窗口的位置、尺寸、内容。
src/main/ets/model/SubWindowOption.ets
export default interface SubWindowOption {
// 小窗名称
subWindowName:string
// 小窗位置
x: number
y: number
// 小窗尺寸
width: number
height: number
// 小窗页面路由地址
subWindowPageUrl: string
}
设计工具类
src/main/ets/common/MySubWindow.ets
import { window } from '@kit.ArkUI';
import SubWindowOption from '../model/SubWindowOption';
class MySubWindow{
windowStage_: window.WindowStage | null = null;
// 小窗口对象
sub_windowClass: window.Window | null = null;
// 创建小窗的方法
async showSubWindow(subWindowOption:SubWindowOption) {
// 1.创建应用子窗口
if (this.windowStage_ == null) {
console.error('dxin => 小窗无法创建,因为 windowStage_ is null');
} else {
this.sub_windowClass = await this.windowStage_.createSubWindow(subWindowOption.subWindowName)
// 2 同步代码 设置小窗 位置和尺寸
this.sub_windowClass.moveWindowToAsync(subWindowOption.x, subWindowOption.y)
this.sub_windowClass.resizeAsync(subWindowOption.width, subWindowOption.height)
// 窗口里面得有内容
this.sub_windowClass.setUIContent(subWindowOption.subWindowPageUrl, () => {
// 让自己显示出来 需要问号或者叹号判空
//this.sub_windowClass!.showWindow()
this.sub_windowClass?.showWindow()
})
}
}
destroySubWindow() {
// 4.销毁子窗口。当不再需要子窗口时,可根据具体实现逻辑,使用destroy对其进行销毁。
//this.sub_windowClass!.destroyWindow()
this.sub_windowClass?.destroyWindow();
}
}
let mySubWindow = new MySubWindow()
export default mySubWindow
在入口类中初始化工具类的windowStage_
src/main/ets/entryability/EntryAbility.ets
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.loadContent('pages/Guide', (err) => {
if (err.code) {
return;
}
// 工具类中的那个主舞台对象 要被真正的主舞台(入口类的)对象赋值
mySubWindow.windowStage_ = windowStage
});
}
设计小窗页面
src/main/ets/pages/SubWindowContent.ets
import mySubWindow from '../common/MySubWindow'
@Entry
@Component
struct SubWindowContent {
build() {
Column({ space: 30 }) {
Text('QQ小窗口').fontSize(22).fontColor('red')
Button('关闭当前小窗口')
.onClick(() => {
mySubWindow.destroySubWindow()
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
在页面中调用工具类开启小窗
src/main/ets/pages/Index.ets
Button('开启QQ的小窗')
.onClick(() => {
mySubWindow.showSubWindow({
subWindowName:"QQ ",
x:50,
y:250,
width:500,
height:500,
subWindowPageUrl:"pages/SubWindowContent"
})
})
问题和优化
无法关闭多个小窗。
以上案例中准备了一个QQ的按钮,点击即可显示QQ的小窗,同时也可在显示的小窗上点击关闭自己。
既然封装工具类,传入参数。目的就是为了创建多个小窗。而以上代码则会出现问题。例如:
在 src/main/ets/pages/Index.ets
再准备一个按钮,准备打开微信的小窗
Button('开启微信的小窗')
.onClick(() => {
mySubWindow.showSubWindow({
subWindowName:"wechat",
x:700,
y:250,
width:500,
height:500,
subWindowPageUrl:"pages/Wechat"
})
})
补充微信小窗对应的页面文件:src/main/ets/pages/Wechat.ets
import mySubWindow from '../common/MySubWindow'
@Entry
@Component
struct Wechat {
build() {
Column({ space: 30 }) {
Text('wechat小窗口').fontSize(22).fontColor('red')
Button('关闭当前小窗口')
.onClick(() => {
mySubWindow.destroySubWindow()
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
此时可以拉起两个小窗口,但是关闭操作无法按照预期实现,分析小窗工具类会发现。每次点击按钮打开窗口都会执行showSubWindow()
方法并创建当前小窗对象,紧接着将创建的小窗对象赋值给工具类的sub_windowClass
属性。
那么:连续创建两个或者多个窗口时,该sub_windowClass
属性存储的是最后一个小窗对象。
所以,点击任何一个小窗的关闭按钮,均会调用和执行工具类中的destroySubWindow()
方法,销毁的正是sub_windowClass
属性中存储的小窗,即,最后一个小窗。 因此,除最后一个小窗可被关闭外,其他小窗对象均无法被关闭。