GXT 3.1.1 的VBoxLayoutContainer 高度BUG

本文解决了VBoxLayoutContainer在展示组件时出现的高度计算错误问题。通过修改源码,实现了每次展示都重新计算高度,并确保了即使组件被隐藏后再次显示也能正常调整布局。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最新使用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();
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FoxMale007

文章非V全文可读,觉得好请打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值