该窗体管理器拥有四个接口:
1.弹出自带左上角返回的全屏界面
WinMgrGetInstance().addBackLayer(layer, exitFunc);
exitFunc 表示关闭时调用的exitFunc,比如刷新操作等
~弹出全屏界面后会隐藏之前弹出的所有界面,无需手动隐藏
2.弹出自带关闭按钮的非全屏界面
WinMgrGetInstance().addPopLayer(layer, exitFunc, {maskShadow: false, maskClose: true, showSingle: false, hideBefore: true});
exitFunc 表示关闭时调用的exitFunc
maskShadow 表示背景mask是否灰态
maskClose 表示点击mask是否关闭当前界面,mask能不能点击到和json也有关
showSingle 表示弹出后是否关闭前一个非全屏界面
hideBefore 表示弹出后是否隐藏前一个非全屏界面
~自带mask,不需要在界面中手动增加mask,避免太暗
~统一移除接口,不要自己通过remove移除当前界面,点击叉叉按钮调用关闭最上层界面进行移除
3.关闭最上层的界面
WinMgrGetInstance().cleanTopLayer();
~会自动显示被隐藏的下一层界面,无须担心
4.关闭所有已打开界面
WinMgrGetInstance().cleanAllLayer();
~切场景的时候要调
~功能跳转操作要调,然后打开新功能
实现代码如下:
WindowManager = cc.Node.extend({
TYPE_BACK : 1,
TYPE_POP : 2,
UI_ZORDER_BASE : 1000,
UI_TAG_BACK : 100,
UI_TAG_MASK : 200,
UI_TAG_BASE : 1000,
_layerlist : [],
ctor: function () {
this._super();
this.initLayer();
this.initBackBtn();
this.initMaskLayer();
},
onEnter:function () {
this._super();
},
onExit: function() {
this._super();
},
initLayer: function() {
this._baseLayer = new cc.Layer();
g_director.getRunningScene().addChild(this._baseLayer, 1000, 9527);
},
initBackBtn: function() {
this._backLayer = op.ResourceManager.getInstance().LoadUIWidget("BackButtonUi_1.json");
this._backLayer.setAnchorPoint(cc.p(0.5,0.5));
this._backLayer.setPosition(g_winCenter);
this._backLayer.setSize(g_winSize);
this._backLayer.setVisible(false);
this._baseLayer.addChild(this._backLayer, this.UI_ZORDER_BASE, this.UI_TAG_BACK);
this._back_btn = this._backLayer.getChildByName("Panel_Back").getChildByName("back");
this._back_btn.addTouchEventListener(LayoutConfig.addTouchEventListener(this.cleanTopLayer, this), this);
var safeArea = LayoutConfig.GetSafeArea();
var back_pos = cc.p(this._back_btn.getPosition().x + safeArea.x, this._back_btn.getPosition().y);
this._back_btn.setPosition(cc.p(back_pos.x-this._back_btn.getContentSize().width, back_pos.y));
this._back_btn.runAction(cc.Sequence.create(
cc.Spawn.create(
cc.MoveTo.create(0.15,cc.p(back_pos.x+this._back_btn.getContentSize().width/3, back_pos.y)),
cc.FadeIn.create(0.15)),
cc.MoveTo.create(0.05, back_pos))
);
},
initMaskLayer: function() {
this._maskLayer = LayoutConfig.attachMask(this._baseLayer, 0, this.UI_TAG_MASK, true);
this._maskLayer.setVisible(false);
},
addBackLayer: function(layer, exitFunc) {
var index = this._layerlist.length + 1;
if (layer) {
var self = this;
var newExitFunc = function() {
if (layer) {
if (exitFunc) {
exitFunc.call(layer);
}
layer.removeFromParent();
layer = null;
self._layerlist.pop();
self.refreshTopLayer();
}
}
// 隐藏之前所有窗体
if (this._layerlist.length > 0) {
for (var i = 0; i < this._layerlist.length; i++) {
if (this._layerlist[i].visible) {
this._layerlist[i].layer.setVisible(false);
this._layerlist[i].visible = false;
}
}
}
this._baseLayer.addChild(layer, index*this.UI_ZORDER_BASE, index*this.UI_TAG_BASE);
this._layerlist.push({index: index, type: this.TYPE_BACK, layer: layer, exitFunc: newExitFunc, visible: true});
this.refreshTopLayer();
}
},
addPopLayer: function(layer, exitFunc, optional = {}) {
var index = this._layerlist.length + 1;
if (layer) {
var self = this;
var newExitFunc = function() {
if (layer) {
if (exitFunc) {
exitFunc.call(layer);
}
layer.removeFromParent();
layer = null;
self._layerlist.pop();
self.refreshTopLayer();
}
}
// 清除或隐藏前一个弹窗窗体
if (optional.showSingle || optional.hideBefore) {
var layerNum = this._layerlist.length;
if (layerNum > 0) {
var topData = this._layerlist[layerNum-1];
if (topData.type == this.TYPE_POP) {
if (optional.showSingle) {
this.cleanTopLayer();
} else {
this._layerlist[layerNum-1].layer.setVisible(false);
this._layerlist[layerNum-1].visible = false;
}
}
}
}
this._baseLayer.addChild(layer, index*this.UI_ZORDER_BASE, index*this.UI_TAG_BASE);
this._layerlist.push({index: index, type: this.TYPE_POP, layer: layer, exitFunc: newExitFunc, visible: true, maskShadow: optional.maskShadow, maskClose: optional.maskClose});
this.refreshTopLayer();
}
},
refreshTopLayer: function() {
var layerNum = this._layerlist.length;
if (layerNum > 0) {
this._layerlist[layerNum-1].visible = true;
var topData = this._layerlist[layerNum-1];
topData.layer.setVisible(true);
if (topData.type == this.TYPE_BACK) {
this._backLayer.setVisible(true);
this._backLayer.setLocalZOrder(topData.index*this.UI_ZORDER_BASE+10);
} else {
// 找出最上层的TYPE_BACK,重置返回按钮zorder
this._backLayer.setVisible(false);
for (var i = layerNum-1; i >= 0; i--) {
if (this._layerlist[i].type == this.TYPE_BACK) {
this._layerlist[i].layer.setVisible(true);
this._layerlist[i].visible = true;
this._backLayer.setVisible(true);
this._backLayer.setLocalZOrder(this._layerlist[i].index*this.UI_ZORDER_BASE+10);
break;
}
}
}
this._maskLayer.setVisible(true);
this._maskLayer.setLocalZOrder(topData.index*this.UI_ZORDER_BASE-10);
this._maskLayer.setBackGroundColorOpacity(topData.maskShadow ? 180 : 0);
if (topData.maskClose) {
this._maskLayer.addTouchEventListener(LayoutConfig.addTouchEventListenerNoAnima(topData.exitFunc, topData.layer), this);
} else {
this._maskLayer.addTouchEventListener(function() {}, this);
}
} else {
this._backLayer.setVisible(false);
this._maskLayer.setVisible(false);
}
},
cleanTopLayer: function() {
var layerNum = this._layerlist.length;
if (layerNum > 0) {
var topData = this._layerlist[layerNum-1];
if (topData.layer) {
topData.exitFunc.call(topData.layer);
} else {
this._layerlist.pop();
this.refreshTopLayer();
}
}
},
cleanAllLayer: function() {
if (this._layerlist.length > 0) {
this.cleanTopLayer();
this.cleanAllLayer();
}
},
});
var g_WindowMgr = null;
var WinMgrGetInstance = function() {
if(!g_WindowMgr){
g_WindowMgr = new WindowManager();
g_WindowMgr.retain();
}
return g_WindowMgr;
};
未完待续:
~需要增加弹出信息框界面并管理
~目前四个接口只在MainScene(主城)上调用才有效,后续进行优化
~根据BaseNode中的_event_tag前缀判断当前打开界面,脚本报错将界面列表上传bugly,增加错误重现概率