阅读 3101

RecyclerView滑动距离计算


二话不说,上图先!

RecyclerView已经出来许久了,估计现在没多少人使用ListView或者GridView了吧?

这篇文章讲解如何计算宽高相同或不同Item的RecyclerView滑动距离,所谓的滑动距离意思如下图。


大概思路就是先得出正在移出屏幕Item的position,再得出该Item的宽或高,再得出该Item还有多少部分未移出屏幕,拿position乘宽或者高减去未移出屏幕的距离,就可以算出滑动的距离了(๑•ᴗ•๑)

先看下定义的变量和常量

//竖着
private static final int MANAGER_LINEAR_VERTICAL = 0;
//横着一行
private static final int MANAGER_LINEAR_HORIZONTAL = 1;
//Grid 竖着
private static final int MANAGER_LINEAR_GRIDVIEW_VERTICAL = 2;
//Grid 横着
private static final int MANAGER_LINEAR_GRIDVIEW_HORIZONTAL = 3;
//竖着不同
private static final int MANAGER_LINEAR_VERTICAL_ = 4;
//横着不同
private static final int MANAGER_LINEAR_HORIZONTAL_ = 5;
//形态变量
private int intType = 0;
//item的宽/高
private int itemW;
private int itemH;
private int iResult;
//存放item宽或高
private Map<Integer, Integer> mMapList = new HashMap<>();
private int iposition;复制代码

Item布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_tk"/>
    <TextView
        android:id="@+id/tv_position"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/iv"
        android:layout_alignTop="@+id/iv"
        android:background="@color/colorPrimary"
        android:textColor="#e5e5e6"
    />
</RelativeLayout>复制代码

一、计算宽高相同Item

//该方法用于监听mRecyclerView的滑动事件
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
    }
});复制代码

在上面监听中调用下面计算方法,可计算出VERTICAL竖着布局的滑动距离

//找到即将移出屏幕Item的position,position是移出屏幕item的数量
int position = linearLayoutManager.findFirstVisibleItemPosition();
//根据position找到这个Item
View firstVisiableChildView = linearLayoutManager.findViewByPosition(position);
//获取Item的高
int itemHeight = firstVisiableChildView.getHeight();
//算出该Item还未移出屏幕的高度
int itemTop = firstVisiableChildView.getTop();
//position移出屏幕的数量*高度得出移动的距离
int iposition = position * itemHeight;
//减去该Item还未移出屏幕的部分可得出滑动的距离
iResult = iposition - itemTop;复制代码

若是HORIZONTAL横着的RecyclerView则需要稍加改动调用下面方法就能计算出滑动距离因为是横着的所以要拿到item的宽,用getRight()方法算出未移出屏幕的距离,但横着的RecyclerView取到的第一个Item Position为零,所以随后算总距离的时候要加上一个Item的宽度

//找到即将移出屏幕Item的position,position是移出屏幕item的数量
int position = linearLayoutManager.findFirstVisibleItemPosition();
//根据position找到这个Item
View firstVisiableChildView = linearLayoutManager.findViewByPosition(position);
//获取Item的宽
int itemWidth = firstVisiableChildView.getWidth();
//算出该Item还未移出屏幕的高度
int itemRight = firstVisiableChildView.getRight();
//position移出屏幕的数量*高度得出移动的距离
int iposition = position * itemWidth;
//因为横着的RecyclerV第一个取到的Item position为零所以计算时需要加一个宽
iResult = iposition - itemRight + itemWidth;复制代码

二、计算Grid排列相同Item

竖着的Grid,注释很认真的写了(⊙o⊙),大部分还是一样的

//得出spanCount几列或几排
int itemSpanCount = gridLayoutManager.getSpanCount();
//得出的position是一排或一列总和
int position = gridLayoutManager.findFirstVisibleItemPosition();
//需要算出才是即将移出屏幕Item的position
int itemPosition = position / itemSpanCount ;
//因为是相同的Item所以取那个都一样
View firstVisiableChildView = gridLayoutManager.findViewByPosition(position);
int itemHeight = firstVisiableChildView.getHeight();
int itemTop = firstVisiableChildView.getTop();
int iposition = itemPosition * itemHeight;
iResult = iposition - itemTop;复制代码

横着的Grid大家可以下Demo看一下,也是有注释的

三、计算不同Item

思路:用Map按Position记录了每个Item的宽或高,通过findFirstVisibleItemPosition()方法动态计算滑动距离

public int unlikeVertical() {
    int itemWH = 0;
    int itemTR = 0;
    int distance = 0;
    int position = linearLayoutManager.findFirstVisibleItemPosition();
    View firstVisiableChildView = linearLayoutManager.findViewByPosition(position);
    //判断是横着还是竖着,得出宽或高
    if (intType == MANAGER_LINEAR_VERTICAL_) {
        itemWH = firstVisiableChildView.getHeight();
    } else if (intType == MANAGER_LINEAR_HORIZONTAL_) {
        itemWH = firstVisiableChildView.getWidth();
    }
    //一层判断mMapList是否为空,若不为空则根据键判断保证不会重复存入
    if (mMapList.size() == 0) {
        mMapList.put(position, itemWH);
    } else {
        if (!mMapList.containsKey(position)) {
            mMapList.put(position, itemWH);
            Log.d("poi", mMapList + "");
        }
    }
    //判断是横着还是竖着,得出未滑出屏幕的距离
    if (intType == MANAGER_LINEAR_VERTICAL_) {
        itemTR = firstVisiableChildView.getTop();
    } else if (intType == MANAGER_LINEAR_HORIZONTAL_) {
        itemTR = firstVisiableChildView.getRight();
    }
    //position为动态获取,目前屏幕Item位置
    for (int i = 0; i < position; i++) {
        //iposition移出屏幕的距离
        iposition = iposition + mMapList.get(i);
    }
    //根据类型拿iposition减未移出Item部分距离,最后得出滑动距离
    if (intType == MANAGER_LINEAR_VERTICAL_) {
        distance = iposition - itemTR;
    } else if (intType == MANAGER_LINEAR_HORIZONTAL_) {
        distance = iposition - itemTR + itemWH;
    }
    //item宽高
    itemW = firstVisiableChildView.getWidth();
    itemH = firstVisiableChildView.getHeight();
    //归零
    iposition = 0;
    return distance;
}
复制代码

Demo地址:github.com/NathansLiu/…

My JianShu:www.jianshu.com/u/ae7a687f5…

写完啦!