Vaadin21中Scroller嵌套多层VerticalLayout滚动异常问题咨询
问题描述
现有场景
- 实现了一个
Composite组件,内部嵌套3层均设置为全高的VerticalLayout - 最内层
VerticalLayout中嵌入了一个Scroller,Scroller内部是包含20个Button的第4个VerticalLayout
期望效果
Composite渲染后,最外层VerticalLayout完整显示在屏幕内,所有布局和Scroller层级嵌套正常- Scroller高度自适应使所有外层内容都适配屏幕可视范围
- 只要屏幕尺寸足以容纳4个
VerticalLayout、1个Scroller和至少1个Button,外层VerticalLayout不会出现滚动条
实际异常
- 最外层
VerticalLayout无法完整适配屏幕,Scroller虽可滚动查看Button,但只有滚动外层3个VerticalLayout才能看到最后一个Button - 滚动外层布局还会出现布局重叠的异常
相关截图
- 初始状态:

- 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; } }
解决方案
问题核心原因是嵌套VerticalLayout的全高设置逻辑错误,以及Scroller内容的高度配置不符合滚动规则,按以下规则调整即可:
- 仅给最外层
VerticalLayout设置全高,其余嵌套层通过flex规则分配高度:每层布局内的标题标签固定占位不扩展,嵌套的下一级组件占满当前层剩余高度 - 移除
Scroller内部内容布局的setHeightFull()配置,让内容高度随按钮数量自然撑开 - 关闭
VerticalLayout默认的内边距,避免额外高度导致溢出
调整后的完整代码如下:
@Route("3_scrollerx") public class ScrollerxView extends Composite<Component> { @Override protected Component initContent() { final VerticalLayout lvl1 = new VerticalLayout(); Label lvl1Label = new Label("lvl1"); final VerticalLayout lvl2 = new VerticalLayout(); Label lvl2Label = new Label("lvl2"); final VerticalLayout lvl3 = new VerticalLayout(); Label lvl3Label = new Label("lvl3"); final Scroller scroller = new Scroller(); scroller.setContent(buildScrollerContent()); // 配置lvl1高度分配 lvl1.add(lvl1Label, lvl2); lvl1.setFlexGrow(1, lvl2); lvl1.setHeightFull(); lvl1.setPadding(false); lvl1.setSpacing(true); lvl1.getStyle().set("border", "1px solid"); // 配置lvl2高度分配 lvl2.add(lvl2Label, lvl3); lvl2.setFlexGrow(1, lvl3); lvl2.setPadding(false); lvl2.setSpacing(true); lvl2.getStyle().set("border", "1px solid"); // 配置lvl3高度分配 lvl3.add(lvl3Label, scroller); lvl3.setFlexGrow(1, scroller); lvl3.setPadding(false); lvl3.setSpacing(true); lvl3.getStyle().set("border", "1px solid"); scroller.getStyle().set("border", "1px solid"); return lvl1; } private VerticalLayout buildScrollerContent() { final var scrollerContent = new VerticalLayout(); for (int i = 1; i <= 20; i++) { scrollerContent.add(new Button("Button " + i)); } // 移除scroller内容的全高设置,让内容自然撑开 return scrollerContent; } }
调整后各层布局会自动分配可视区域高度,Scroller会占满最内层布局的剩余高度,内容超出时仅Scroller内部滚动,外层不会出现滚动条。
内容的提问来源于stack exchange,提问作者sk_dev
相关产品推荐
相关产品推荐

