【问题标题】:Vaadin 21: Nesting Scroller into VerticalLayout problemVaadin 21:将 Scroller 嵌套到 VerticalLayout 问题中
【发布时间】:2021-09-29 06:19:04
【问题描述】:

给定一个 Composite 和 3 个嵌套的 VerticalLayouts,每个都有全高
还有一个Scroller 嵌套在最里面的VerticalLayout
Scroller 包含第四个 VerticalLayout 和 20 个 Buttons

Composite 被渲染时

然后我希望最外面的VerticalLayout 在屏幕上完全可见
VerticalLayouts 和滚动条嵌套整齐
Scroller 与所需一样小,因此所有内容都适合屏幕
并且根本不可能滚动外部的VerticalLayouts(只要屏幕足够大,可以容纳4个VerticalLayouts、一个Scroller,以及至少一个Button

但是最外面的VerticalLayout 不适合屏幕
Scroller 允许滚动浏览 Buttons,但最后一个 Button 只有在滚动 3 个外部 VerticalLayouts 时才能看到(这不应该发生)。
滚动 3 个外部 VerticalLayouts 会显示外部 VerticalLayouts 的奇怪重叠。

初始状态

Scroller滚动到底部后

将整个画布滚动到底部后

如何实现所需的嵌套/滚动行为?

这是我的代码

@Route("3_scrollerx")
public class ScrollerxView extends Composite<Component> {
    @Override
    protected Component initContent() {
        final VerticalLayout lvl1 = new VerticalLayout(new Label("lvl1"));
        final VerticalLayout lvl2 = new VerticalLayout(new Label("lvl2"));
        final VerticalLayout lvl3 = new VerticalLayout(new Label("lvl3"));
        final Scroller scroller = new Scroller();
        scroller.setContent(buildScrollerContent());
        scroller.setHeightFull();

        List.of(lvl1, lvl2, lvl3).forEach(layout -> {
            layout.setHeightFull();
            layout.getStyle().set("border", "1px solid");
        });
        scroller.getStyle().set("border", "1px solid");

        lvl1.add(lvl2);
        lvl2.add(lvl3);
        lvl3.add(scroller); // always weird
        return lvl1;
    }


    private VerticalLayout buildScrollerContent() {
        final var scrollerContent = new VerticalLayout();
        for (int i = 1; i <= 20; i++) {
            scrollerContent.add(new Button("Button " + i));
        }
        scrollerContent.setHeightFull();
        return scrollerContent;
    }
}

【问题讨论】:

  • 布局内的标签也保留了一些空间。尝试扩展嵌套布局,而不是 setHeightFull,以便它们只占用剩余空间,而不是父高度的 100%。
  • 一定有一个误解:我假设setHeightFull(相当于setHeight("100%"))总是相对于周围的布局。那是错的吗?此外,如果我使用 ButtonsetHeightFull() 而不是 Scroller,它会按预期工作。

标签: vaadin vaadin-flow


【解决方案1】:

我在第一次创建我的 Vaadin 应用程序的主要布局时处理了这个问题。它实际上是 flexbox 布局的样式问题,而不是特定于 Vaadin。 VerticalLayout 对象的计算最小高度是其内容的高度。如果您在垂直布局上设置 css min-height: 0,它将允许它们小于其内容。

您可以在这里了解更多信息:

由于开发人员忘记设置最小高度,这一直作为我们的回归出现。 VerticalLayout 很方便,但其中包含许多主题和样式,可以很好地显示单独的控件。如果您正在寻找可重用的 flexbox 组件来构建页面,请考虑创建一个新组件。

@Tag("column-layout")
@CssImport("layouts.css")
public class ColumnLayout extends Div {
    public ColumnLayout(Component... components) {
        super(components);
    }
}

采用这种风格:

column-layout {
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

在您的示例中实现:

@Route("3_scrollerx")
public class ScrollerxView extends Composite<Component> {

    @Override
    protected Component initContent() {
        final ColumnLayout lvl1 = new ColumnLayout(new Label("lvl1"));
        final ColumnLayout lvl2 = new ColumnLayout(new Label("lvl2"));
        final ColumnLayout lvl3 = new ColumnLayout(new Label("lvl3"));

        VerticalLayout scrollerContent = buildScrollerContent();
        List.of(lvl1, lvl2, lvl3, scrollerContent).forEach(layout -> {
            layout.setHeightFull();
            layout.getStyle().set("border", "1px solid");
        });

        lvl1.add(lvl2);
        lvl2.add(lvl3);
        lvl3.add(scrollerContent);
        return lvl1;
    }


    private VerticalLayout buildScrollerContent() {
        final var scrollerContent = new VerticalLayout();
        for (int i = 1; i <= 20; i++) {
            scrollerContent.add(new Button("Button " + i));
        }
        scrollerContent.getStyle().set("overflow", "auto");
        return scrollerContent;
    }
}

【讨论】:

  • 非常感谢您的全面解释。它按描述工作。
猜你喜欢
  • 1970-01-01
  • 2021-11-27
  • 1970-01-01
  • 2015-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-24
  • 2022-01-02
相关资源
最近更新 更多