首页 > 代码库 > cocos2dx的ui封装

cocos2dx的ui封装

cocos2dx里加载cocosudio导出的ui配置文件,在这之上封装了一下,封装核心类包括

UIManager,UILayer,UIOwner

UIManager是所有ui总的管理类,代码如下:

UIManager = {
battle = 1,
city = 2,
login = 4,
select = 8,
create = 16,
-- room = 32,
movie = 64,
dance = 128,
arena = 256,
house = 512,
format = 1024,
dress = 2048,
astro = 4096,
cook = 8192,
god = 16384,
video = 32768,
boss = 32768*2,
fish = 32768*4,
farm = 32768*8,
spa = 32768*16,
pokersel= 32768*32,
poker = 32768*64,
back = 32768*128,
none = 0,
all = 0xffffffff,

bottom = 1,
game = 2,
pop = 3,
high = 4,
top = 5,
}
_class( "UIManager", Object );

local instance
function UIManager.getInstance()
if not instance then
instance=UIManager:new();
end
return instance;
end

function UIManager.new( self )
local instance = Object.new( self );
instance._layer=cc.Layer:create();
instance:addLayer(UILayer:new(), UILayer:new(), UILayer:new(),UILayer:new(),UILayer:new());
return instance
end

function UIManager.getLayer( self, layer )
return array.indexOf( self.layers, layer );
end

function UIManager.addLayer( self, ... )
for i = 1, select("#", ...) do
local layer = select(i, ...);
layer.owner = self;
table.insert(self.layers, layer)
self._layer:add(layer, i)
end
end

function UIManager.addSwf( self, swfowner, lay, depth )
self.layers[lay]:add( swfowner, depth );
end

function UIManager.removeSwf( self, swfowner )
if not swfowner.container then return; end;
swfowner.container:remove( swfowner );
end

function UIManager.enterDomain( self, domain )
for i = 1, #self.layers do
self.layers[i]:enterDomain(domain);
end
self.domain = domain;
end

function UIManager.onIdle(self, e)
for i = 1, #self.layers do
self.layers[i]:onIdle(e)
end
end

function UIManager.disMe(self)
end

UIOwner是每个ui的实例,UIManager分层管理UIOwner,UILayer的代码如下:

UILayer = {}
_class( "UILayer", EventDispatcher )

function UILayer.new( self )
local instance = Object.new( self );
instance.uis = {}; -- collections of uiowner
instance.depths = {};
instance._layer=cc.Layer:create();
return instance;
end

function UILayer.add( self, ui, depth )
depth = depth or self:getNextDepth();
local len=#self.uis;
for i = 1, len do
if self.uis[i] == ui then
self:topui(self.uis[j]):top();
for j = i+1, table.maxn( self.uis ) do
self:topui(self.uis[j]):top();
end
return;
end
end
local i = 1;
while i <= len do
if self.depths[i] > depth then
break;
end
i = i + 1;
end
table.insert( self.uis, i, ui );
table.insert( self.depths, i, depth );
self:topui(ui);
i = i + 1;
while i <= len+1 do
self:topui(self.uis[i]);--排序
i = i + 1;
end
ui.container = self;
end

function UILayer.pop( self, ui )
for i = 1, table.maxn( self.uis ) do
if self.uis[i] == ui then
table.remove( self.uis, i );
table.remove( self.depths, i );
self._layer:removeChild(ui._ui);
return ui;
end
end
end

function UILayer.topui(self, ui)
ui:setlocalZOrder(self:getNextDepth())
end

function UILayer.remove( self, ui )
for i = 1, table.maxn( self.uis ) do
if self.uis[i] == ui then
self.uis[i]:disMe();
table.remove( self.uis, i );
table.remove( self.depths, i );
self._layer:removeChild(ui._ui);
return;
end
end
end

function UILayer.setDepth( self, ui, depth )
local i = array.indexOf( self.uis, ui );
if ( not self.depths[i-1] or self.depths[i-1] < depth ) and ( not self.depths[i+1] or self.depths[i+1] > depth ) then
self.depths[i] = depth;
return;
elseif depth > self.depths[i] then
self:topui(ui);
table.remove( self.depths, i );
table.remove( self.uis, i );
local binsert = false;
for ii = i + 1, #self.uis do
if self.depths[ii] > depth then
if not binsert then
table.insert( self.uis, ii , ui );
table.insert( self.depths, ii, depth );
binsert = true;
end
self:topui(self.uis[ii]);
end
end
if not binsert then
table.insert( self.uis, ui );
table.insert( self.depths, depth );
end
elseif depth < self.depths[i] then
table.remove( self.depths, i );
table.remove( self.uis, i );
local binsert = false;
for ii = 1, #self.uis do
if self.depths[ii] > depth then
if not binsert then
table.insert( self.uis, ii , ui );
table.insert( self.depths, ii, depth );
binsert = true;
end
self:topui(self.uis[ii]);--排序
end
end
if not binsert then
table.insert( self.uis, ui );
table.insert( self.depths, depth );
end
end
end

function UILayer.getLayer( self )
return self.owner:getLayer( self );
end

function UILayer.getDepth( self, ui )
local i = array.indexOf( self.uis, ui );
return self.depths[i];
end

function UILayer.top( self, ui ) -- uiowner
local i = array.indexOf( self.uis, ui );
if i == table.maxn( self.uis ) then return; end
table.remove( self.uis, i );
table.remove( self.depths, i );
table.insert( self.uis, ui );
local depth=self:getNextDepth();
table.insert( self.depths, depth );
self._layer:_setLocalZOrder(depth);
end

function UILayer.getNextDepth( self )
if table.maxn( self.depths ) == 0 then return 1 end;
return toint( self.depths[table.maxn( self.depths )] + 1 ) ;
end

function UILayer.onIdle(self, e)
for i = 1, #self.uis do
if self.uis[i]:isShow() then
self.uis[i]:onIdle(e);
end
end
end

function UILayer.clear( self )
for _, ui in next, self.uis do
ui:disMe();
end
self.uis = {};
self.depths = {};
return self;
end

UIOwner是每个ui的封装的,其中_ui属性对应加载进来node对象,代码如下:

local function loadui(res)
return ccs.GUIReader:shareReader():widgetFromJsonFile("res/SampleChangeEquip_1.json");
end

UIOwner={}
_class("UIOwner", Object)
function UIOwner.new(self, url, layer, depth, domain)
local instance=Object.new(self)
self._ui=loadui(url);
_uimanager:addSwf( instance, lay, depth );
instance.domain = domain or UIManager.none;
instance._name = url;
SwfOwner.show( instance, true );
return self
end

function UIOwner.isShow(self)
return self._show;
end

function UIOwner.show(self, b)
b = toboolean(b);
local os = self:isShow();
if os ~= b then
self._show = b;
end
if self:isShow() then
self:onResize();
elseif os then
fadeclear(self);
end
return self;
end

function UIOnwer.onIdle(self, e)
end

function UIOwner.disMe(self)

end

下面举个登录的例子:

LoginUI={}
_class("LoginUI", UIOwner)
function LoginUI.new(self)
local instance=Object.new(self, "login.luf", 1, UIManager.login)
instance:setClick();
return instance;
end

function LoginUI.show(self, b)
local os=self:isShow();
SwfOwner.show(self, b);
if self:isShow() then
if not os then
self:updateInfo()
end
end
return self;
end

function LoginUI.updateInfo()
end

还有个全局的show方法如下:

function showLoginUI ( b )
local name = "loginui";
if uiargs["showLoginUI"] then
uiargs["showLoginUI"]= {b};
local oldDomain = _swfs.manager.domain;
return;
end
if not _swfs[name] then
if b == false then return; end
uiargs["showLoginUI"] = {b};
callinWait(true);
local oldDomain = UIManager:getInstance().domain;
local process = UIProcess:getInstance():show(true);
local loader = _Loader.new();
loader:onFinish(function()
_swfs[name] = LoginUI:new():show(false);
local args = uiargs["showLoginUI"];
uiargs["showLoginUI"]=nil;
if _swfs[name]:checkDomain(oldDomain) then
showLoginUI(unpack(args));
end

process:close();uiloaders[loader]=nil;
callinWait(false);
end);
loader:onProgress(function(per) process:setProgress(toint(per*100)); end)
loader:load( "loginui.luf" );uiloaders[loader]=loader
print(loader.progress);
return;
end
local oldShow = _swfs[name]:isShow();
b = ( b == nil and not _swfs[name]:isShow() ) or b;
if b and b ~= oldShow then
end
_swfs[name]:show( b );
end

整个封装的两点好处在于:

 1其他的ui实现以及show方法和这个非常相似,实际中的代码是是用工具生成,可以极大加快开发速度,估计不是很复杂的界面,一天能完成4-6个左右界面

2不直接操作引用,对Ui的操作都是通过方法实现的,可以杜绝内存泄露,而且因为所有的实例生成都从object.new走 ,可以实现1个通用的monitor,监视对象实例个数,便于查找lua对象泄露

整个封装是从原来的页游项目拷贝修改过的,原来的底层实现是通过scaleform加载swf,即使底层实现不一样,但是上层封装可以做到一致,这个封装与底层实现耦合度低(曾经用flash as实现过基本一样的封装)

整个搬过来的时候,没有调试过,等之后的场景封装完事之后,都调通了,会再上传1份完整点的包