如何使用md-virtual-repeat在两个方向上进行无限滚动?

时间:2018-03-15 18:43:44

标签: angularjs angularjs-ng-repeat infinite-scroll angularjs-material

我已经实施了infinite horizontal scroll using md-virtual-repeat。当我向右滚动时,每次需要时它会获取25条记录。

<md-virtual-repeat-container flex md-orient-horizontal>
  <div md-virtual-repeat="item in $ctrl.infiniteItems" md-on-demand>
    {{ item.date }}
  </div>
</md-virtual-repeat-container>

基本上它是一个水平的日期列表(包含其他信息),您可以滚动。滚动到将来的日期。工作正常。

现在,我想滚动到过去日期的左侧。

我正在寻找一种从中间开始的方式(今天的日期是这样)。我已尝试在控制器上设置md-top-index一个值,但在从服务器获取第一页后,它会重置为较低的数字。

<md-virtual-repeat-container flex md-orient-horizontal md-top-index="$ctrl.topIndex">
  <div md-virtual-repeat="item in $ctrl.infiniteItems" md-on-demand>
    {{ item.date }}
  </div>
</md-virtual-repeat-container>

如何配置md-virtual-repeat-containermd-virtual-repeat以允许向左和向右滚动?

更新:这是一个带有Codepen的沙箱,我希望能够容纳一个向左滚动的按钮。 https://codepen.io/christiaanwesterbeek/pen/pLRQgg

Update2:将md-top-index设置为某个正整数可以向两个方向滚动。但是角度材质网站md-top-index给出的example与无限滚动无关。我的问题的解决方案是md-top-index遇到无限滚动的地方。

1 个答案:

答案 0 :(得分:0)

嗯..回答你的问题:

您可以通过将body文档的html标记更改为<body dir="rtl">

,允许在md-virtual-repeat的反方向滚动

快速破解:

我到处寻找这个,但我找不到任何东西,我认为你也做了,所以我从angular cdn 本地下载了angular-material.js,看看他们是如何处理的,这里是一个片段:

VirtualRepeatContainerController.prototype.handleScroll_ = function() {
  var ltr = document.dir != 'rtl' && document.body.dir != 'rtl';
  if(!ltr && !this.maxSize) {
    this.scroller.scrollLeft = this.scrollSize;
    this.maxSize = this.scroller.scrollLeft;
  }
  var offset = this.isHorizontal() ?
      (ltr?this.scroller.scrollLeft : this.maxSize - this.scroller.scrollLeft)
      : this.scroller.scrollTop;

  if (offset === this.scrollOffset || offset > this.scrollSize - this.size) return;

  var itemSize = this.repeater.getItemSize();
  if (!itemSize) return;

  var numItems = Math.max(0, Math.floor(offset / itemSize) - NUM_EXTRA);

  var transform = (this.isHorizontal() ? 'translateX(' : 'translateY(') +
      (!this.isHorizontal() || ltr ? (numItems * itemSize) : - (numItems * itemSize))  + 'px)';

  this.scrollOffset = offset;
  this.offsetter.style.webkitTransform = transform;
  this.offsetter.style.transform = transform;

  if (this.bindTopIndex) {
    var topIndex = Math.floor(offset / itemSize);
    if (topIndex !== this.topIndex && topIndex < this.repeater.getItemCount()) {
      this.topIndex = topIndex;
      this.bindTopIndex.assign(this.$scope, topIndex);
      if (!this.$rootScope.$$phase) this.$scope.$digest();
    }
  }

  this.repeater.containerUpdated();
};

这就是我发现他们依靠身体的方向指导无限滚动的方式,所以如果你不想改变html文件的方向,你必须下载它,编辑这个部分并使用它来代替cdn,但是它不会按预期工作;

在正常情况下,从左向右滚动会增加this.scrollLeft变量,正如您在整个代码段中看到的那样,它会增加offsettranslateX()和一切都会落到正确的地方,

但如果您从右向左滚动,handleScroll_功能会将this.scrollOfsset设置为视图的宽度,当您向左滚动时,this.scrollLeft会减少而不是增加,一旦你达到你的前25的结束,一切都将分崩离析,

我尝试了内部所有变量的console.log,并将rtlltr进行了比较,看看事情发生的时间和地点,我尝试使用值和操作,但没有成功,随意做同样的实验也许我错过了一些东西(但是嘿,问题只是关于改变方向吗?:P)

我建议你去寻找别的东西(比如上面评论中的那些)

我希望这有助于或至少给你一个想法,祝​​你好运。

编辑:

因为这取决于body的方向,所以即使您设置md-top-index并从中间开始(dir="ltr"),也可以向左或向右滚动,而不是同时向左滚动,如果你回去,你只会在一侧(右侧)进行无限滚动,它只是显示旧的已加载数据,

您可以查看VirtualRepeatController.prototype.virtualRepeatUpdate_文件中的js,了解它如何添加新块以及更新索引和滚动。

旁注:人们想要这个用于反向垂直滚动(用于聊天应用)并且存在未解决的问题,但由于它们移动到角度2.x及以上

,因此不太可能添加

底线是:如果你只想配置两侧滚动,我恐怕你不能,如果你绝对想要这个,你将不得不修改angular-material.js以满足你的需求