# 如何解决Scroll组件设置高度限制后，无法顶部对齐的问题

## 问题现象

在实现滚动列表效果时，由于加载的数据数量不确定，比如购物车场景时。需要实现在数据较多时列表能正常滚动，数据较少时，数据能从顶部开始排布。但是当Scroll组件设置layoutWeight属性时，如果数据较少，Scroll居中排布，无法实现顶部对齐效果。不设置layoutWeight属性时数据少可以实现顶部对齐，但是数据过多时会导致数据展示不全。即：Scroll组件设置高度与不设置高度会产生不同的排布效果。项目结构如下：

```screen
Column() {
  Text()
  Scroll()
}
```

## 效果预览

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/b7/v3/tS7HZIZcT9u1IY1xvIaxZg/zh-cn_image_0000002658794587.gif?HW-CC-KV=V1&HW-CC-Date=20261028T113910Z&HW-CC-Expire=31536000000&HW-CC-Sign=E767CBD8BA806C927C7BA340CC1808C72AD9874822B5920BF2B0F02AC29149E7 "点击放大")

## 背景知识

* [Scroll组件](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-scroll)：该组件是可滚动的容器组件，当子组件的布局尺寸超过Scroll组件的尺寸时，内容可以滚动。同时，若子组件的布局尺寸小于Scroll组件的尺寸时，则Scroll组件不可滚动，且默认居中排布。
* [align](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-location#align)：该属性是组件的通用位置设置属性，可以设置组件内子组件的排布方式，其参数枚举详见：[Alignment](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-appendix-enums#alignment)。
* [layoutWeight](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-size#layoutweight)：该属性为组件的通用属性，用于设置组件的布局权重，使用该属性的组件在父容器（Row/Column/Flex）的主轴方向按照各子组件的layoutWeight属性参数大小的比值分配父组件剩余尺寸。

## 问题定位

针对Scroll组件设置高度与不设置高度会产生不同的排布效果的分析如下（Scroll组件为深灰色）：

* Scroll未设置layoutWeight时： 若此时没有设置Scroll组件的其它高度限制，比如.height属性，则Scroll组件会自适应内部子组件的总高度（最高为屏幕显示高度，也就是0~100%的高度）。此时若是Scroll的父组件为[Column组件](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-column)，由于Column组件默认自上而下排布，所以Scroll组件会从Column的顶部开始布局。

  ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/1/v3/P_Cu931GTMCu-gjiY4xdbg/zh-cn_image_0000002628555220.gif?HW-CC-KV=V1&HW-CC-Date=20261028T113910Z&HW-CC-Expire=31536000000&HW-CC-Sign=EC37AF5BC80CE39722DEB80E30C844DF5B0A48CB6546ACBE9E5B46C2D29913EC "点击放大")

  由图片现象可知，Scroll组件没有高度限制时，高度随子组件高度变化。当Scroll背景颜色与页面背景颜色一致时，布局满足列表从顶部开始排列。但是数据过多时，由于Scroll组件高度会被子组件撑到屏幕高度的100%，若Scroll组件上方有其它兄弟组件，会导致Scroll展示不全，底部被挤出显示区。滚动列表展示不全的相关问题可参考行业常见问题：[List展示不全](https://developer.huawei.com/consumer/cn/doc/harmonyos-faqs/faqs-arkui-1126)。
  > 说明
  >
  > Scroll未设置高度限制时，顶部对齐效果是Scroll组件从父组件Column组件顶部开始布局，并不是Scroll子组件从Scroll顶部开始布局。


* Scroll设置layoutWeight时： 此时相当于给了Scroll组件的高度限制，其高度为父组件除去其它子组件后的剩余高度。Scroll子组件的布局尺寸小于Scroll组件的尺寸时，其子组件默认居中排布，问题复现如下：

  ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/7d/v3/C1i0xMI4R2qb_35cYWBSAg/zh-cn_image_0000002658914541.gif?HW-CC-KV=V1&HW-CC-Date=20261028T113910Z&HW-CC-Expire=31536000000&HW-CC-Sign=1255DD15CC1F37D2445FF2767494FF966B665209C534C2990445C39D51BD9ABF "点击放大")

  由图片现象可知，Scroll组件设置高度限制后，当其内数据较少时，默认居中排布。

## 分析结论

Scroll组件需要设置高度限制，否则若Scroll背景颜色与页面背景颜色不一致时，会有显示问题，且若Scroll上方存在兄弟组件，Scroll组件过高时会展示不全。当设置Scroll组件高度后，可以通过设置.align(Alignment.Top)属性实现Scroll子组件顶部排布效果。

## 修改建议

通过以下方式可实现列表数据较少时顶部对齐，数据较多时可滚动的效果：

* **方案一** ：Scroll组件设置高度限制，同时增加.align(Alignment.Top)属性。

  ```screen
  @Entry
  @Component
  export struct SceneOne {
    private scroller: Scroller = new Scroller();
    @State arr: string[] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13'];
    @State arr1: string[] = ['1', '2', '3', '4'];
    @State arr2: string[] = [];
    @State value: boolean = true;

    build() {
      Column() {
        Text('我是标题，点击我更新数据')
          .width('100%')
          .margin({
            top: 10,
            bottom: 10
          })
          .textAlign(TextAlign.Center)
          .onClick(() => {
          // 点击刷新数据
            if (this.value) {
              this.arr2 = this.arr;
            } else {
              this.arr2 = this.arr1;
            }
            this.value = !this.value;
          })
        Scroll(this.scroller) {
          Column() {
            ForEach(this.arr2, (item: string) => {
              Column() {
                Text('数据' + item)
                  .textAlign(TextAlign.Start)
                  .fontSize(18)
              }
              .width('95%')
              .height(72)
              .backgroundColor(Color.White)
              .borderRadius(12)
              .justifyContent(FlexAlign.Center)
              .margin({
                top: 6,
                bottom: 6
              })
            })
          }
        }
        .scrollBar(BarState.Off)
        .width('95%')
        .align(Alignment.Top) // Scroll组件内部子组件按照顶部开始排列
        .layoutWeight(1)// Scroll组件自动占满父组件剩余部分
        .backgroundColor(Color.Gray)
      }
      .width('100%')
      .height('100%')
    }
  }
  ```

* **方案二** ：可以采用List组件实现。

  [List组件](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-list)在限制过高度后，当其子组件高度小于List组件高度时，默认从顶部开始排布。参考方案一，核心修改代码如下：

  ```screen
  @Entry
  @Component
  export struct SceneTwo {
    @State arr: string[] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13'];
    @State arr1: string[] = ['1', '2', '3', '4'];
    @State arr2: string[] = [];
    @State value: boolean = true;

    build() {
      Column() {
        Text('我是标题，点击我更新数据')
          .width('100%')
          .margin({
            top: 10,
            bottom: 10
          })
          .textAlign(TextAlign.Center)
          .onClick(() => {
            //点击刷新数据
            if (this.value) {
              this.arr2 = this.arr;
            } else {
              this.arr2 = this.arr1;
            }
            this.value = !this.value;
          })
        List() {
          ForEach(this.arr2, (item: string) => {
            ListItem() {
              Column() {
                Column() {
                  Text('数据' + item)
                    .fontSize(18)
                }
                .justifyContent(FlexAlign.Center)
                .width('95%')
                .height(72)
                .backgroundColor(Color.White)
                .borderRadius(12)
              }
              .justifyContent(FlexAlign.Center)
              .width('100%')
            }
            .margin({
              top: 6,
              bottom: 6
            })
          })
        }
        .scrollBar(BarState.Off)
        .width('95%')
        .layoutWeight(1) // List组件自动占满父组件剩余部分
        .backgroundColor(Color.Gray)
      }
      .width('100%')
      .height('100%')
    }
  }
  ```

## 总结

1. Scroll组件在未设置高度时，其高度跟随子组件高度自适应。可以实现数据量少时，数据从顶部开始排列，但是数据较多时，Scroll组件会默认撑开到屏幕的100%高度，当Scroll上方有其它兄弟组件时，会出现Scroll显示不全的问题。
2. 当Scroll组件设置高度限制后，若子组件高度小于Scroll组件高度，则默认居中排布，可以采用.align(Alignment.Top)通用属性使其从顶部开始排布。
3. 由于List组件在设置高度限制后，若子组件高度小于List组件高度时是默认从顶部开始排布，所以也可以用List组件替代Scroll组件。

