Android开发 解决RecyclerView in SwipeRefreshLayout触发下拉刷新的bug

来源:互联网 发布:mac 提醒事项 红点 编辑:程序博客网 时间:2024/06/05 19:51

Android开发 解决RecyclerView in SwipeRefreshLayout触发下拉刷新的bug

转载请注明 作者:田野光 地址:http://blog.csdn.net/lovefish2/article/details/45921041

首先我们来看一下会遇到的问题:

我们知道, SwipeRefreshLayout 会监听滑动操作,并相应触发下拉刷新,如果布局文件中内含了可滑动的控件,如ScrollView等,则很有可能会在错误的时候触发下拉刷新(譬如当你下拉页面想要浏览上方内容), 好消息是所有AbsListView 子类,包括listview, ExpandableListView 等控件,只要是XML布局内部的直接下级,SwipeRefreshLayout都内置了判断方法,可以避免错误的触发.不过其他情况就需要单独处理了.

说解决办法前,我们先看一下SwipeRefreshLayout的源码:

public boolean canChildScrollUp() {        if (android.os.Build.VERSION.SDK_INT < 14) {            if (mTarget instanceof AbsListView) {                final AbsListView absListView = (AbsListView) mTarget;                return absListView.getChildCount() > 0                        && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)                                .getTop() < absListView.getPaddingTop());            } else {                return ViewCompat.canScrollVertically(mTarget, -1) || mTarget.getScrollY() > 0;            }        } else {            return ViewCompat.canScrollVertically(mTarget, -1);        }    }

很容易发现, SwipeRefreshLayout只处理了直接下级布局为AbsListView类型的情况, 所以我们目前的做法只能自定义SwipeRefreshLayout,修改其中canChildScrollUp方法,增加对RecyclerView情况的判断.

public boolean canChildScrollUp() {        if (mTarget instanceof RecyclerView) {            final RecyclerView recyclerView = (RecyclerView) mTarget;            RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();            if (layoutManager instanceof LinearLayoutManager) {                int position = ((LinearLayoutManager) layoutManager).findFirstCompletelyVisibleItemPosition();                return position != 0;            } else if (layoutManager instanceof StaggeredGridLayoutManager) {                int[] positions = ((StaggeredGridLayoutManager) layoutManager).findFirstCompletelyVisibleItemPositions(null);                for (int i = 0; i < positions.length; i++) {                    if (positions[i] == 0) {                        return false;                    }                }            }            return true;        } else if (android.os.Build.VERSION.SDK_INT < 14) {            if (mTarget instanceof AbsListView) {                final AbsListView absListView = (AbsListView) mTarget;                return absListView.getChildCount() > 0                        && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)                        .getTop() < absListView.getPaddingTop());            } else {                return mTarget.getScrollY() > 0;            }        } else {            return ViewCompat.canScrollVertically(mTarget, -1);        }    }

将新的文件命名为CustomSwipeRefreshLayout.java, 并同时复制其他几个依赖文件到项目中,最后问题解决.

<CustomSwipeRefreshLayout        android:layout_width="match_parent"        android:layout_height="match_parent">        <android.support.v7.widget.RecyclerView            android:layout_width="match_parent"            android:layout_height="wrap_content"/></CustomSwipeRefreshLayout>
1 0