最新使用VBoxLayoutContainer自动计算高度。希望像GXT2.3一样可以自动适应高,但是始终发现高度怎么算也算不对,老是被截取了一段。难道我每次hide和show一些组件要自己再计算一次高度?。。。要疯掉。
于是开始尝试,发现每展示一次,就要缩短一截。问题大约可以定位了,应该在resize或render位置。于是继续debug,经过数小时折腾后,最后发现问题如下:
第一次展示,容器是没有原高度,所有高度计算正确。当第二次展示时,采用第一次高度重新计算。计算的算法都一点问题没有,催悲的是,第二次重新显示计算的高度,从容器取出来就要比实际展示的要小!使用这个值重新计算,肯定高度要缩短了。
想了半天,没想出更好的办法。于是拿源码开刀,把依据上次的高度来计算的代码砍掉砍掉,每次强制重新计算高度。。。
最后代码如下:
/**
*
* 修复VerticalLayout的自动高度计算问题.
* 解决办法:1.清理上级高度 2.每次都重新计算整体高度(支持对象隐藏)
*
* @author JIM
*
*/
public class CcVBoxLayoutContainer extends VBoxLayoutContainer {
@Override
protected void doLayout() {
Size size = getElement().getSize();
int w = size.getWidth() - getScrollOffset();
int h = size.getHeight();
int styleWidth = Util.parseInt(getElement().getStyle().getProperty("width"), Style.DEFAULT);
boolean findWidth = styleWidth == -1;
int calculateHeight = 0;
int maxWidgetWidth = 0;
int maxMarginLeft = 0;
int maxMarginRight = 0;
for (int i = 0, len = getWidgetCount(); i < len; i++) {
Widget widget = getWidget(i);
BoxLayoutData layoutData = null;
Object d = widget.getLayoutData();
if (d instanceof BoxLayoutData) {
layoutData = (BoxLayoutData) d;
} else {
layoutData = new BoxLayoutData();
widget.setLayoutData(layoutData);
}
Margins cm = layoutData.getMargins();
if (cm == null) {
cm = new Margins(0);
layoutData.setMargins(cm);
}
}
for (int i = 0, len = getWidgetCount(); i < len; i++) {
Widget widget = getWidget(i);
if (!widget.isVisible()) {
continue;
}
BoxLayoutData layoutData = (BoxLayoutData) widget
.getLayoutData();
Margins cm = layoutData.getMargins();
calculateHeight += widget.getOffsetHeight();
maxWidgetWidth = Math.max(maxWidgetWidth,
widget.getOffsetWidth());
calculateHeight += (cm.getTop() + cm.getBottom());
maxMarginLeft = Math.max(maxMarginLeft, cm.getLeft());
maxMarginRight = Math.max(maxMarginRight, cm.getRight());
}
maxWidgetWidth += (maxMarginLeft + maxMarginRight);
h = calculateHeight;
if (findWidth) {
w = maxWidgetWidth;
}
int pl = 0;
int pt = 0;
int pb = 0;
int pr = 0;
if (getPadding() != null) {
pl = getPadding().getLeft();
pt = getPadding().getTop();
pb = getPadding().getBottom();
pr = getPadding().getRight();
}
h += pt + pb;
if (findWidth) {
w += pl + pr;
}
int stretchWidth = w - pl - pr;
int totalFlex = 0;
int totalHeight = 0;
int maxWidth = 0;
for (int i = 0, len = getWidgetCount(); i < len; i++) {
Widget widget = getWidget(i);
widget.addStyleName(CommonStyles.get().positionable());
widget.getElement().getStyle().setMargin(0, Unit.PX);
// callLayout(widget, false);
BoxLayoutData layoutData = (BoxLayoutData) widget.getLayoutData();
Margins cm = layoutData.getMargins();
totalFlex += layoutData.getFlex();
totalHeight += widget.getOffsetHeight() + cm.getTop()
+ cm.getBottom();
maxWidth = Math.max(maxWidth,
widget.getOffsetWidth() + cm.getLeft() + cm.getRight());
}
int innerCtWidth = maxWidth + pl + pr;
if (getVBoxLayoutAlign().equals(VBoxLayoutAlign.STRETCH)) {
getContainerTarget().setSize(w, h, true);
} else {
getContainerTarget().setSize(w = Math.max(w, innerCtWidth), h, true);
}
int extraHeight = h - totalHeight - pt - pb;
int allocated = 0;
int cw, ch, cl;
int availableWidth = w - pl - pr;
if (getPack().equals(BoxLayoutPack.CENTER)) {
pt += extraHeight / 2;
} else if (getPack().equals(BoxLayoutPack.END)) {
pt += extraHeight;
}
for (int i = 0, len = getWidgetCount(); i < len; i++) {
Widget widget = getWidget(i);
BoxLayoutData layoutData = (BoxLayoutData) widget.getLayoutData();
Margins cm = layoutData.getMargins();
cw = widget.getOffsetWidth();
ch = widget.getOffsetHeight();
pt += cm.getTop();
if (getVBoxLayoutAlign().equals(VBoxLayoutAlign.CENTER)) {
int diff = availableWidth - (cw + cm.getLeft() + cm.getRight());
if (diff == 0) {
cl = pl + cm.getLeft();
} else {
cl = pl + cm.getLeft() + (diff / 2);
}
} else {
if (getVBoxLayoutAlign().equals(VBoxLayoutAlign.RIGHT)) {
cl = w - (pr + cm.getRight() + cw);
} else {
cl = pl + cm.getLeft();
}
}
boolean component = widget instanceof Component;
Component c = null;
if (component) {
c = (Component) widget;
}
int height = -1;
if (component) {
c.setPosition(cl, pt);
} else {
XElement.as(widget.getElement()).setLeftTop(cl, pt);
}
if (getPack().equals(BoxLayoutPack.START)
&& layoutData.getFlex() > 0) {
int add = (int) Math.floor(extraHeight
* (layoutData.getFlex() / totalFlex));
allocated += add;
if (isAdjustForFlexRemainder() && i == getWidgetCount() - 1) {
add += extraHeight - allocated;
}
ch += add;
height = ch;
}
if (getVBoxLayoutAlign().equals(VBoxLayoutAlign.STRETCH)) {
applyLayout(widget, Util.constrain(stretchWidth - cm.getLeft()
- cm.getRight(), layoutData.getMinSize(),
layoutData.getMaxSize()), height);
} else if (getVBoxLayoutAlign().equals(VBoxLayoutAlign.STRETCHMAX)) {
applyLayout(widget, Util.constrain(
maxWidth - cm.getLeft() - cm.getRight(),
layoutData.getMinSize(), layoutData.getMaxSize()),
height);
} else if (height > 0) {
applyLayout(widget, -1, height);
}
pt += ch + cm.getBottom();
}
getElement().getParentElement().getStyle().clearHeight(); //清理上级高度
getElement().getStyle().clearHeight();
}
}