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

前言

最近遇到需求,要计算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));

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

(0)

相关推荐

  • Android中ScrollView实现滑动距离监听器的方法

    前言 众所周知ScrollView是我们经常使用的一个UI控件,也许你在使用ScrollView的过程中会发现,当你想监听ScrollView滑动的距离时却没有合适的监听器!当然在API 23中有setOnScrollChangeListener(View.OnScrollChangeListener l)可以使用,但是并不兼容低版本的API.那怎么办呢?只好重写ScrollView来实现对滑动距离的监听了. 话不多说,直接上代码: public class MyScrollView exten

  • JS手机端touch事件计算滑动距离的方法示例

    本文实例讲述了JS手机端touch事件计算滑动距离的方法.分享给大家供大家参考,具体如下: 计算手势在手机屏幕上滑动时,手势滑动的距离,代码如下: function wetherScroll(){ var startX = startY = endX =endY =0; var body=document.getElementsByTagName("body"); body.bind('touchstart',function(event){ var touch = event.tar

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

    前言 最近遇到需求,要计算RecyclerView滑动距离,用提供的computeVerticalScrollOffset()方法得到的值不是很准确.是基于item的平均高度算得,如果列表中item高度一致可以用此方法.问题来了,我的应用场景是各item高度不一,这时就只能另找方法了. 方法一: 网上找的方法,用一个变量去统计,每次滑动的时候累加y轴偏移量.item插入\移动\删除的时候,需要手动去更新totalDy,不然就会一直错下去. private int totalDy = 0; mRe

  • js获取滚动距离的方法

    本文实例讲述了js获取滚动距离的方法.分享给大家供大家参考.具体实现方法如下: /** / THIRD FUNCTION * getPageScroll() by quirksmode.com * * @return Array Return an array with x,y page scroll values. */ function ___getPageScroll() { var xScroll, yScroll; if (self.pageYOffset) { yScroll = s

  • Android获取RecyclerView滑动距离方法详细讲解

    先说能用的究极解决方案,大家着急的直接复制走,以后想了解再过来看 没有header,且所有Item的高度一致 private fun getScrollYDistance(recyclerView: RecyclerView): Int? { kotlin.runCatching { val layoutManager = recyclerView.layoutManager as LinearLayoutManager val position = layoutManager.findFirs

  • Android中RecyclerView实现滑动删除与拖拽功能

    前言 从Android 5.0开始,谷歌推出了新的控件RecyclerView,相对于早它之前的ListView,优点多多,功能强大,也给我们的开发着提供了极大的便利,今天自己学习一下RecyclerView轻松实现滑动删除及拖拽的效果. 如下图. 相信研究过RecyclerView的同学,应该很清楚该怎么实现这样的效果,若是用ListView,这样的效果实现起来可能就有点麻烦,但是在强大的RecyclerView面前这样的的效果只需很少的代码,因为谷歌给我们提供了强大的工具类ItemTouch

  • JS获取鼠标位置距浏览器窗口距离的方法示例

    本文实例讲述了JS获取鼠标位置距浏览器窗口距离的方法.分享给大家供大家参考,具体如下: 先来看看运行效果图: 代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> #test_div { width:400px; height: 400px;

  • Android中RecyclerView嵌套滑动冲突解决的代码片段

    在纵向RecyclerView嵌套横向RecyclerView时,如果纵向RecyclerView有下拉刷新功能,那么内部的横向RecyclerView的横向滑动体验会很差.(只有纯横向滑动时,才能滑动内部的横向RecyclerView,否则滑动事件就会影响到下拉刷新),添加拦截判断. public class MySwipeRefreshLayout extends SwipeRefreshLayout { private boolean mIsVpDragger; private final

  • Android嵌套RecyclerView左右滑动替代自定义view

    以前的左右滑动效果采用自定义scrollview或者linearlayout来实现,recyclerview可以很好的做这个功能,一般的需求就是要么一个独立的左右滑动效果,要么在一个列表里的中间部分一个左右滑动效果 而列表里面也容易,只是需要解决一点小问题,个人认为值得一提的就是高度问题,一般的人采用固定死的高度,可是在列表里面展示和机型的不同,固定死的话很难保证美观,动态的高度才能解决问题的所在 首先在一个列表控件布局上添加一个recyclerview控件 <android.support.v

  • js jquery 获取某一元素到浏览器顶端的距离实现方法

    如下所示: <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <style> body{ margin: 0; padding: 0; } .mdiv{ width: 100px; height: 100px; background-color: red; } </style> </head> <bod

  • jquery获取元素到屏幕四周可视距离的方法

    实例如下: $(window).height();//是文档窗口高度 $("div").offset().top//是标签距离顶部高度(没有到下面的距离,比如$("div").offset().down) $("div").offset().left//是标签距离右边高度(没有到下面的距离,比如$("div").offset().right) $(document).scrollTop();//是滚动条高度 $("d

随机推荐