-- 自动布局的方向 ScreenLayoutDir = { -- 左边 SL_Left = 1, -- 下面 SL_Bottom = 2, -- 右边 SL_Right = 3, -- 上面 SL_Top = 4, } -- 全屏自动把一个控件绕着一个控件水平布局 -- rect 控件的矩形(x,y,width,height)都是屏幕坐标系,锚点在0,0,即xy是这个控件的左下角 -- pos 参考点,被控制的控件始终以这个参考点的轴向为主要参照(屏幕坐标) -- size 被控制的控件的大小(屏幕坐标) -- @return 返回被控制的控件的屏幕坐标,假设控件的锚点在0,0,即计算出来是被控制的控件的左下角位置 function screenLayout(rect , pos , size , screenSize, dir) screenSize = screenSize or cc.Director:getInstance():getWinSize(); local targetPos = nil if dir then -- 左边 if dir == ScreenLayoutDir.SL_Left then targetPos = cc.p(rect.x - size.width, pos.y - size.height / 2); elseif dir == ScreenLayoutDir.SL_Bottom then targetPos = cc.p(pos.x, rect.y - size.height); elseif dir == ScreenLayoutDir.SL_Right then targetPos = cc.p(rect.x + rect.width, pos.y - size.height / 2); elseif dir == ScreenLayoutDir.SL_Top then targetPos = cc.p(pos.x, rect.y + rect.height); end -- 必须都要限制在定义的区域里面 targetPos.x = cc.clampf(targetPos.x , 0 , screenSize.width - size.width); targetPos.y = cc.clampf(targetPos.y , 0 , screenSize.height - size.height); return targetPos else -- 计算左边位置(历史遗留问题) targetPos = cc.p(rect.x - size.width , pos.y - size.height / 2); -- 左边没越界,说明放得下 if targetPos.x >= 0 then targetPos.y = cc.clampf(targetPos.y , 0 , screenSize.height - size.height); return targetPos; -- 左边放不下,放右边吧 else targetPos.x = rect.x + rect.width; targetPos.y = cc.clampf(targetPos.y , 0 , screenSize.height - size.height); return targetPos; end end end -- 全屏布局函数 -- nodeContainer 布局容器节点 -- nodePoint 布局参考点的节点 -- nodeTarget 被布局的节点 function screenLayoutNode(nodeContainer , nodePoint , nodeTarget , screenSize, dir) local rect = nodeContainer:getWorldRect(); local pos = nodePoint:getParent():convertToWorldSpace2D(cc.p(nodePoint:getLeftInParent() , nodePoint:getBottomInParent())); local size = nodeTarget:getContentSize(); local targetPos = screenLayout(rect , pos , size , screenSize, dir); local targetToParentPos = nodeTarget:getParent():convertToNodeSpace2D(targetPos); local targetAp = nodeTarget:getAnchorPoint(); targetToParentPos.x = targetToParentPos.x + targetAp.x * size.width targetToParentPos.y = targetToParentPos.y + targetAp.y * size.height nodeTarget:setPosition(targetToParentPos); end -- 自动执行的全屏布局 -- nodeContainer 布局容器节点 -- nodePoint 布局参考点的节点 -- nodeTarget 被布局的节点 -- dir表示强制放到那个方向(如果放不下就往里面挤挤) function autoScreenLayoutNode(nodeContainer , nodePoint , nodeTarget, screenSize, dir) local function onUpdate() screenLayoutNode(nodeContainer , nodePoint , nodeTarget, screenSize, dir); end -- 每帧更新一次 schedule(nodeTarget , onUpdate , 0); onUpdate(); return onUpdate; end -- 自动执行的全屏布局(当nodeContainer或者nodePoint不存在了则停止布局) -- nodeContainer 布局容器节点 -- nodePoint 布局参考点的节点 -- nodeTarget 被布局的节点 function autoScreenLayoutNodeEx(nodeContainer , nodePoint , nodeTarget , screenSize) local layoutAction = nil local function onUpdate() if tolua.isnull(nodeContainer) or tolua.isnull(nodePoint) then local function stopLayoutAction() if not tolua.isnull(nodeTarget) and not tolua.isnull(layoutAction) then nodeTarget:stopAction(layoutAction) layoutAction = nil end end runInNextFrame(stopLayoutAction) else -- 更新 screenLayoutNode(nodeContainer , nodePoint , nodeTarget , screenSize); end end -- 每帧更新一次 layoutAction = schedule(nodeTarget , onUpdate , 0); onUpdate(); return onUpdate; end