cocos creator从零开发简单框架(11)-顶层遮挡
有这样一个场景,当点击了某个按钮,但它可能要跟后端交互并且会花费一定时间,这个时候不能再次点击按钮。要实现这个功能,一般是添加一个标志位,当点击后设为一个状态,当处理完逻辑后设为初始状态。这个实现如果项目多处用到就比较麻烦,换一种方式,直接在顶层添加一个Block Input Events
组件就行。
新建framework/scripts/view/TopBlock.ts
,内容如下。主要就是生成一个节点,把它挂载在Top
层级并铺满屏幕,调用show
方法时,显示这个节点拦截所有点击事件,调用hide
方法隐藏这个节点。
import AppConstants from "../AppConstants"
import AppUtil from "../AppUtil"
import LayerMgr from "./LayerMgr"
export default class TopBlock {
private static _view: cc.Node
public static show() {
this.ensure()
LayerMgr.setLayer(this._view, AppConstants.viewLayer.Top)
this._view.active = true
}
public static hide() {
if (!this._view || !this._view.isValid) return
this._view.active = false
}
private static ensure() {
if (this._view && this._view.isValid) return
this._view = new cc.Node('TopBlock')
this._view.opacity = 0
AppUtil.setWidget(this._view)
this._view.addComponent(cc.BlockInputEvents)
}
}
修改UIMgr.ts
脚本,在加载UI
资源可能有延迟的地方调用TopBlock.show()
方法,结束的地方调用TopBlock.hide()
方法。
编辑framework/scripts/view/UIMgr.ts
,修改show
方法。
private static async show(cls: UIBase, uiArgs: any[]) {
TopBlock.show()
const viewName = cls.getClassName()
let current = this._uis.get(viewName)
if (!current) {
current = cls
current.uiName = viewName
const [uiPrefab, err] = await AppUtil.asyncWrap<cc.Prefab>(ResMgr.load(current.bundleName, current.skinPath))
if (err) {
TopBlock.hide()
console.error(`UIMgr.show loadRes skinPath:${current.skinPath} err:${err}`)
return
}
current.init(uiArgs)
current.skin = cc.instantiate(uiPrefab)
current.initDone()
this._uis.set(viewName, current)
} else {
current.reset(uiArgs)
}
this.startShowUI(current)
}
修改showUIAfter
方法。
private static showUIAfter(current: UIBase) {
TopBlock.hide()
this._current = current
}
编辑scripts/UIMain.ts
,重载onInitDone
方法。
import TopBlock from "../framework/scripts/view/TopBlock"
import UIBase from "../framework/scripts/view/UIBase"
import UIMgr from "../framework/scripts/view/UIMgr"
import UIBag from "./UIBag"
export default class UIMain extends UIBase {
public skinPath: string = 'UIMain'
public cache: boolean = true
protected onInitDone(): void {
// 因为 UIMgr 在 onInitDone 生命周期结束后会调用 TopBlock.hide(), 所以为了测试这里加个 100 毫秒的延迟
setTimeout(() => {
TopBlock.show()
cc.log('这个时候点击无效')
setTimeout(() => {
TopBlock.hide()
cc.log('现在可以点击了')
}, 10000)
}, 100)
}
protected onButtonClick(button: cc.Node) {
switch (button.name) {
case 'BtnUIBag':
UIMgr.open(UIBag)
break
}
}
}
运行程序,发现Main
界面刚开始是不能点击背包
按钮的,等过了 10 秒后就能点击了。
本作品采用《CC 协议》,转载必须注明作者和本文链接