Layout组件使用以下配置:
效果如下图所示
cocosCreator版本:1.9.2
这个效果明显不是我想要的,我想要的效果是卡牌不论有多少张,它们在垂直方向都能居中,而在实际效果图中我们看到明显是往上偏移了。
此时,观察到我们的这个Layout组件的高度值仅有一个卡牌高度的量(如一张卡牌高度是100,那么两张卡牌高度本应该是200,而我们这个Layout的实际高度仅有100),所以可以得到一个结论:问题出在Layout的高度计算代码有误。
解决方案
新建一个JavaScript文件,然后使其继承自cc.Layout,然后重写它在GRID这种Type情况下的垂直方向布局方法。
cc.Class({
extends: cc.Layout,
properties: {
},
//覆盖父类同名方法,代码取自父类方法,仅修改几个小细节
_doLayoutGridAxisHorizontal(layoutAnchor, layoutSize){
var baseWidth = layoutSize.width;
var sign = 1;
var bottomBoundaryOfLayout = -layoutAnchor.y * layoutSize.height;
var paddingY = this.paddingBottom;
if (this.verticalDirection === cc.Layout.VerticalDirection.TOP_TO_BOTTOM) {
sign = -1;
bottomBoundaryOfLayout = (1 - layoutAnchor.y) * layoutSize.height;
paddingY = this.paddingTop;
}
//修改处1:此处根据sign的不同使用不同计算方式
var fnPositionY = function(child, topOffset, row) {
return sign === 1 ? (bottomBoundaryOfLayout + topOffset + child.anchorY * child.height + paddingY + row * this.spacingY) :
(bottomBoundaryOfLayout - topOffset - (1 - child.anchorY) * child.height - paddingY - row * this.spacingY);
}.bind(this);
//修改处2:resizeMode === CONTAINER时的高度计算方式修改
this._doLayoutHorizontally(baseWidth, true, fnPositionY, true);
if (this.resizeMode === cc.Layout.ResizeMode.CONTAINER) {
var minY = Number.MAX_VALUE, maxY = Number.MIN_VALUE;
for(var c of this.node.children)
{
if (c.activeInHierarchy) {
var b = c.getBoundingBox();
if(b.yMin < minY)minY = b.yMin;
if(b.yMax > maxY)maxY = b.yMax;
}
}
var newHeight = maxY - minY;
this.node.setContentSize(baseWidth, newHeight);
bottomBoundaryOfLayout = sign === 1 ? (-layoutAnchor.y * newHeight) : ((1 - layoutAnchor.y) * newHeight);
this._doLayoutHorizontally(baseWidth, true, fnPositionY, true);
}
}
});
使用此Javascript文件替代Layout作为布局组件即可解决问题,当然,要是你想修改官方cc.Layout的源码也行,就是步骤多一点,而且升级ccc之后还得重新写一遍。希望官方人员看到此贴后可以及时修改Layout中相关高度计算的源码。不过我这个只给出了自适应高度的计算代码,全当抛砖引玉了,自适应宽度的计算代码在此就不写了