如何使用具有相对大小的 ScrollPanel

How to use ScrollPanel with relative size

我正在尝试在页面中使用 GWT 的 ScrollPanel。由于大部分内容都在 ScrollPanel 中,我希望它占据页面的尽可能大的部分,并随着页面大小的调整而调整大小。当然,我想将它设置为相对大小,即 setSize("100%","100%")。但是文档说它只能以绝对 CSS 单位设置大小(例如“10px”、“1em”,但不是“50%”)

我不明白为什么 ScrollPanel 不能在 GWT 中获取相对大小。经过大量搜索和阅读后,有人建议将元素的大小设置为“100%”(参见 GWT Relative Width)。我可以尝试一下,但不确定它是否会影响 ScrollPanel 的其他功能 - 因为我还将控制面板的滚动。

ScrollPanel myScrollPanel = new ScrollPanel();
myScrollPanel.setSize("2112px", "150px");   // Arbitrary width.
myScrollPanel.getElement().getStyle().setProperty("width", "100%");  

所以这是我的问题:

(1) 为什么??? (这让我很生气,因为我无法理解,也许对GWT内部机制有更深入了解的人可以赐教)

(2) 如何解决?

你第一个问题的答案很简单。使用元素的相对大小时,您指的是父元素的大小。因此,当您设置 height: 100% 时,这意味着您的元素应该是其父元素大小的 100%。

还有一些方法可以得到你想要的:

  • 使用 Viewport-percentage lengths - 您可以设置 height: 100vh,这意味着 100% of the viewport height - 这是最简单的方法,但可能尚未被所有浏览器支持

  • htmlbody 元素的高度都设置为 100% - 这将允许您在子元素上使用相对高度

  • 使用 GWT DockLayoutPanel or DockPanel 并将滚动面板添加到 center 窗格 - 这将占用所有剩余的 space

ScrollPanel 实现了 RequiresResize 接口,这意味着它需要从 parent 中获取它的大小,或者它的大小必须明确设置。因此,您有两个选择。

(1) 使用实现 ProvidesResize 接口的 parent 小部件 - 例如 LayoutPanel。然而,重要的是,ProvidesResize - RequiresResize 链从 RootPanel 到 ScrollPanel 一直保持完整。

在典型的实现中,LayoutPanel(或其变体)代表整个页面。然后你可以添加各种 children 到它,例如"header"、"main view"、"left menu" 等。对于每个 child,您可以设置首选大小。例如:

myLayoutPanel.setWidgetTopBottom(myScrollPanel, 32, Unit.PX, 0, Unit.PX); 

在此示例中,您的 ScrollPanel 将获取页面上从顶部 32 像素开始一直到底部的所有可用 space。您可以将其位置设置为百分比或其他单位。

(2) 你可以用纯CSS完成同样的布局。如果您不关心非常旧的浏览器,最好的选择是使用 flexbox layout model。在这种情况下,您在 parent 小部件上设置 display: flex,在 ScrollPanel 上设置 flex-grow: 1 - 告诉它获取所有可用的 space(除非还有其他 flex-grow兄弟姐妹,在这种情况下,他们将平分额外的 space).

首先,ScrollPanel 不能充当其他小部件,我不知道为什么。无法设置相对大小 (50%),如果我给它一些样式,它会丢失某处,无法从页面中找到。

我的解决方案是使用 ResizeLayoutPanel。 Andrei 建议使用 ProvidesResize,但要求 provide / require resize 链保持完整,这可能非常棘手。我找到了这个 ResizeLayoutPanel "ProvidesResize to its one child, but does not RequiresResize",它是我的组合的根面板的完美候选者。然后,只要父级 ResizeLayoutPanel 调用它,我就扩展 ScrollPanel 以在 "onResize" 方法中调整自身大小。

我的第一个问题仍然没有答案:ScrollPanel 最初的行为是这样的?我试图在它的源代码中找到答案但没有成功(虽然我没有花足够的时间研究源代码)。

public class My100PctScrollPanel extends ScrollPanel {
    @Override
    public void onResize() {
        // Window.alert("on resize"); 
        this.setWidth(this.getParent().getOffsetWidth()+"px");
        this.setHeight(this.getParent().getOffsetHeight()+"px");
        super.onResize();
    }
}

........

compositeRoot = new ResizeLayoutPanel();  

........
scrollPanel = new My100PctScrollPanel();
compositeRoot.clear();
compositeRoot.add(scrollPanel);