编辑framework/scripts/AppConstants.ts
,内容如下。定义了Panel
的显示方式和遮罩类型,遮罩类型可以叠加,即可同时拥有不可穿透
、半透明
、关闭组件
特性。
// Panel 显示方式
public static readonly panelShowStyle = {
// 正常出现
Normal: 1,
// 中间变大
CenterSmallToBig: 2,
// 上往中
UpToCenter: 3,
// 下往中
DownToCenter: 4,
// 左往中
LeftToCenter: 5,
// 右往中
RightToCenter: 6,
// 自定义
Custom: 7,
}
// Panel 遮罩类型
public static readonly panelMaskStyle = {
// 不可穿透
NoThrough: 0b1,
// 半透明
Black: 0b10,
// 关闭组件
Close: 0b100,
}
新建framework/scripts/view/PanelBase.ts
,内容如下。定义了显示方式
、遮罩类型
及Panel
显示的过渡时长。
import AppConstants from "../AppConstants"
import ViewBase from "./ViewBase"
export default class PanelBase extends ViewBase {
public panelName: string
public panelShowStyle: number = AppConstants.panelShowStyle.Normal
public panelMaskStyle: number = AppConstants.panelMaskStyle.NoThrough
public duration: number = 0.2
}
新建framework/scripts/view/PanelMgr.ts
,内容如下。
import AppConstants from "../AppConstants"
import AppUtil from "../AppUtil"
import ResMgr from "../manager/ResMgr"
import LayerMgr from "./LayerMgr"
import PanelBase from "./PanelBase"
import TopBlock from "./TopBlock"
export default class PanelMgr {
// 所有面板
private static _panels: Map<string, PanelBase> = new Map()
// 显示 Panel
public static async show(panelCls: any, ...panelArgs: any[]) {
TopBlock.show()
const cls = new panelCls() as PanelBase
const viewName = cls.getClassName()
const current = cls
current.panelName = viewName
const [panelPrefab, err] = await AppUtil.asyncWrap<cc.Prefab>(ResMgr.load(current.bundleName, current.skinPath))
if (err) {
TopBlock.hide()
console.error(`PanelMgr.show load bundleName:${current.bundleName},skinPath:${current.skinPath},err:${err}`)
return
}
current.init(panelArgs)
current.skin = cc.instantiate(panelPrefab)
current.initDone()
LayerMgr.setLayer(current.skin, AppConstants.viewLayer.Panel)
this._panels.set(viewName, current)
current.skin.active = false
current.showing()
this.startShowPanel(current, current.panelShowStyle, true)
}
// 隐藏 Panel
public static hide(panelName: string) {
if (!this._panels.has(panelName)) {
console.error(`PanelMgr.hide 面板[${panelName}]不存在`)
return
}
const pb = this._panels.get(panelName)
if (!pb.skin.active) {
console.error(`PanelMgr.hide 面板[${panelName}]已隐藏`)
return
}
TopBlock.show()
this.startShowPanel(pb, pb.panelShowStyle, false)
}
// 销毁 Panel
public static destroy(panelName: string) {
if (!this._panels.has(panelName)) {
console.error(`PanelMgr.destroy 面板[${panelName}]不存在`)
return
}
let pb = this._panels.get(panelName)
pb.hiding()
pb.skin.active = false
pb.hided()
this._panels.delete(panelName)
pb.destroy()
pb = null
}
private static startShowPanel(go: PanelBase, showStyle: number, isOpen: boolean) {
switch (showStyle) {
case AppConstants.panelShowStyle.Normal:
this.showNormal(go, isOpen)
break
}
}
//#region 显示方式
/** 默认显示 */
private static showNormal(go: PanelBase, isOpen: boolean) {
if (isOpen) {
go.skin.active = true
go.showed()
} else {
this.destroy(go.panelName)
}
this.showPanelAfter()
}
//#endregion
private static showPanelAfter() {
TopBlock.hide()
}
}
参考UIMain
,创建一个新的PanelYellow
,创建一个名为BtnClose
文本为关闭
的按钮,然后把 PanelYellow
节点拖动到resources
目录下并从场景删除。
新建scripts/PanelYellow.ts
,内容如下。
import AppUtil from "../framework/scripts/AppUtil"
import PanelBase from "../framework/scripts/view/PanelBase"
import PanelMgr from "../framework/scripts/view/PanelMgr"
export default class PanelYellow extends PanelBase {
public skinPath: string = 'PanelYellow'
protected onButtonClick(button: cc.Node) {
if (button.name == 'BtnClose') {
PanelMgr.hide(AppUtil.getClassName(PanelYellow))
}
}
}
编辑UIMain
界面,创建一个名为BtnPanelYellow
文本为黄面板
的按钮。
编辑scripts/UIMain.ts
, onButtonClick
方法添加如下代码。
case 'BtnPanelYellow':
PanelMgr.show(PanelYellow)
break
运行程序,点击黄面板
按钮,打开PanelYellow
界面,然后点击关闭
按钮,也能正确关闭面板。虽然面板的打开和关闭都正常了,但还存在两个问题,一是PanelMgr.hide(AppUtil.getClassName(PanelYellow))
这行代码多了AppUtil.getClassName
这一步调用比较繁琐,二是打开面板后还能点击黄色面板区域以外的按钮。我们先解决第一个问题,第二个问题下个章节处理。
编辑framework/scripts/view/PanelBase.ts
,添加close
和closeImmediate
方法。
// 关闭面板(有动画)
public close() {
PanelMgr.hide(this.panelName)
}
// 关闭面板(无动画, 立即关闭)
public closeImmediate() {
PanelMgr.destroy(this.panelName)
}
编辑scripts/PanelYellow.ts
,修改PanelMgr.hide(AppUtil.getClassName(PanelYellow))
这一行为this.close()
,再次运行程序,一样能正确关闭面板。也可以试下改成this.closeImmediate()
关闭面板,发现是一样的效果,因为目前面板打开和关闭就是设置面板为true
或者false
。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。