欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

item高度不同时Recyclerview获取滑动距离的方法

程序员文章站 2023-10-30 18:24:34
前言 最近遇到需求,要计算recyclerview滑动距离,用提供的computeverticalscrolloffset()方法得到的值不是很准确。是基于item的...

前言

最近遇到需求,要计算recyclerview滑动距离,用提供的computeverticalscrolloffset()方法得到的值不是很准确。是基于item的平均高度算得,如果列表中item高度一致可以用此方法。问题来了,我的应用场景是各item高度不一,这时就只能另找方法了。

方法一

网上找的方法,用一个变量去统计,每次滑动的时候累加y轴偏移量。item插入\移动\删除的时候,需要手动去更新totaldy,不然就会一直错下去。

private int totaldy = 0;
mrecycler.addonscrolllistener(new recyclerview.onscrolllistener() {
  @override
  public void onscrolled(recyclerview recyclerview, int dx, int dy) {
    totaldy -= dy;
  }
}

方法二:

方法一比较麻烦,而且坑较多。所以考虑重写linearlayoutmanager的computeverticalscrolloffset()方法,既然原生方法是按平均高度计算的,那重写该计算逻辑,就能达到我们想要的效果。

1.统计列表已展示过的item的高度,在每次布局完成的时候,用一个map记录positon位置item对应的view的高度。

private map<integer, integer> heightmap = new hashmap<>();
int count = getchildcount();
for (int i = 0; i < count; i++) {
  view view = getchildat(i);
  heightmap.put(i, view.getheight());
}

2.重写computeverticalscrolloffset(),找到当前屏幕第一个可见item的position,通过heightmap循环累加0到positon的item高度,再加上第一个可见item不可见部分高度。最终得到整个列表的滑动偏移。

@override
public int computeverticalscrolloffset(recyclerview.state state) {
  if (getchildcount() == 0) {
    return 0;
  }
  int firstvisiableposition = findfirstvisibleitemposition();
  view firstvisiableview = findviewbyposition(firstvisiableposition);
  int offsety = -(int) (firstvisiableview.gety());
  for (int i = 0; i < firstvisiableposition; i++) {
    offsety += heightmap.get(i) == null ? 0 : heightmap.get(i);
  }
  return offsety;
}

3.最终代码

public class offsetlinearlayoutmanager extends linearlayoutmanager {

  public offsetlinearlayoutmanager(context context) {
    super(context);
  }

  private map<integer, integer> heightmap = new hashmap<>();

  @override
  public void onlayoutcompleted(recyclerview.state state) {
    super.onlayoutcompleted(state);
    int count = getchildcount();
    for (int i = 0; i < count ; i++) {
      view view = getchildat(i);
      heightmap.put(i, view.getheight());
    }
  }

  @override
  public int computeverticalscrolloffset(recyclerview.state state) {
    if (getchildcount() == 0) {
      return 0;
    }
    try {
      int firstvisiableposition = findfirstvisibleitemposition();
      view firstvisiableview = findviewbyposition(firstvisiableposition);
      int offsety = -(int) (firstvisiableview.gety());
      for (int i = 0; i < firstvisiableposition; i++) {
        offsety += heightmap.get(i) == null ? 0 : heightmap.get(i);
      }
      return offsety;
    } catch (exception e) {
      return 0;
    }
  }
}

mrecycler.setlayoutmanager(new offsetlinearlayoutmanager(mcontext));

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。