使用CDK自动调整虚拟滚动策略保持滚动位置

7

使用CDK autosize虚拟滚动策略保持滚动位置

我有一个大型的项目列表,可以使用由@angular/cdk-experimental提供的<cdk-virtual-scroll-viewport autosize>进行滚动(项目具有动态高度,因此我使用了这个滚动策略,而不是FixedSizeVirtualScrollStrategy)。

新项目随着时间的推移插入到列表中,即它们附加在顶部。当用户向下滚动时,我希望避免新项目将视口中的项目推开。因此,我需要一种机制,在项添加后维护/恢复滚动位置。

我有一个半工作的解决方案(很巧妙,因为它读取私有字段),但视口在项添加后会随机移动几个像素。

以下是相关的代码部分:

@ViewChild(CdkVirtualScrollViewport) viewport: CdkVirtualScrollViewport;

...

// After new items have been added:

const offset = this.viewport.measureScrollOffset('top');
const topPosition = offset + newItems.length * this.viewport['_scrollStrategy']._averager._averageItemSize; // the autosize strategy determines an average item size I'm trying to use to determine how the viewport should be shifted

this.viewport.scrollTo({
  top: topPosition
});

我在这里创建了一个演示案例: https://stackblitz.com/edit/angular-be926g?file=src/app/cdk-virtual-scroll-overview-example.ts 有没有什么想法可以在恒定的视口下实现这一点?

你可以考虑将新数据存储在另一个属性中,并在滚动窗口顶部设置通知。当接收到新数据时,用户可以决定是否需要加载新数据。 - Owen Kelvin
1个回答

2

您可以使用this.viewport.getRenderedRange()来检查视口是否在顶部,如果为零,则将元素附加到顶部,否则将元素保留在存储桶中,并在用户滚动到视口顶部时附加对象。

  const range = this.viewport.getRenderedRange();
  console.log("range", range);
  bucket = [...bucket, ...newItems];
  console.log("bucket", bucket);
  if (range.start == 0) {
    this.items = [...bucket.reverse(), ...this.items];
    bucket = [];
  }

stackblitz 示例


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接