在android 2.2中使用RecyclerView刷新滚动SwipeRefreshLayout

问题描述 投票:0回答:7

我的布局有问题,我创建了带有 RecyclerView 的 SwipeRefreshLayout 。 在 android 4.2.2+ 中一切都工作良好,但在 andorid 2.3.4 中我无法向上滚动,因为在 RecyclerView 中的任何位置它都会刷新,我必须向下滚动然后向上滚动。

这是我的代码:

<android.support.v4.widget.SwipeRefreshLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/forum_swipe_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/LVP"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="center" />
</android.support.v4.widget.SwipeRefreshLayout>

我发现了这个问题:https://code.google.com/p/android/issues/detail?id=78191但没有解决方案。 知道如何解决吗?

android android-recyclerview swiperefreshlayout
7个回答
11
投票

重写RecyclerView的方法

OnScrollStateChanged

 mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                // TODO Auto-generated method stub
                //super.onScrollStateChanged(recyclerView, newState);
               try {
                   int firstPos = mLayoutManager.findFirstCompletelyVisibleItemPosition();
                   if (firstPos > 0) {
                       mSwipeRefreshLayout.setEnabled(false);
                   } else {
                       mSwipeRefreshLayout.setEnabled(true);
                       if(mRecyclerView.getScrollState() == 1)
                           if(mSwipeRefreshLayout.isRefreshing())
                            mRecyclerView.stopScroll();
                   }

               }catch(Exception e) {
                   Log.e(TAG, "Scroll Error : "+e.getLocalizedMessage());
               }
            }

检查滑动刷新是否正在刷新并尝试向上滚动然后出现错误,因此当滑动刷新正在进行时我尝试执行此操作

mRecyclerView.stopScroll();


6
投票

我使用以下代码修复了向上滚动问题:

private RecyclerView.OnScrollListener scrollListener = new RecyclerView.OnScrollListener() {
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        LinearLayoutManager manager = ((LinearLayoutManager)recyclerView.getLayoutManager());
        boolean enabled =manager.findFirstCompletelyVisibleItemPosition() == 0;
        pullToRefreshLayout.setEnabled(enabled);
    }
};

然后您需要使用

setOnScrollListener
addOnScrollListener
,具体取决于您是否有一个或多个听众。


5
投票

不幸的是,这是一个已知问题,将在未来版本中修复。

https://code.google.com/p/android/issues/detail?id=78191

同时,如果您需要紧急修复,请覆盖

canChildScrollUp
中的
SwipeRefreshLayout.java
并致电
recyclerView.canScrollVertically(mTarget, -1)
。因为
canScrollVertically
是在姜饼之后添加的,所以您还需要复制该方法并在 recyclerview 中实现。

或者,如果您使用 LinearLayoutManager,则可以调用

findFirstCompletelyVisibleItemPosition

抱歉给您带来不便。


3
投票

您可以根据recyclerview的滚动能力禁用/启用刷新布局

    public class RecyclerSwipeRefreshHelper extends RecyclerView.OnScrollListener{

    private static final int DIRECTION_UP = -1;


    private final SwipeRefreshLayout refreshLayout;

    public RecyclerSwipeRefreshHelper(
            SwipeRefreshLayout refreshLayout) {
        this.refreshLayout = refreshLayout;
    }


    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
       refreshLayout.setEnabled((recyclerView.canScrollVertically(DIRECTION_UP)));
    }
}

1
投票

您可以像这样重写 SwipeRefreshLayout 中的 canChildScrollUp() 方法:

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);
    }
}

0
投票

基于@wrecker的回答(https://stackoverflow.com/a/32318447/7508302)。

在Kotlin中我们可以使用扩展方法。所以:

class RecyclerViewSwipeToRefresh(private val refreshLayout: SwipeToRefreshLayout) : RecyclerView.OnScrollListener() {
    companion object {
        private const val DIRECTION_UP = -1
    }

    override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
        super.onScrolled(recyclerView, dx, dy)
        refreshLayout.isEnabled = !(recyclerView?.canScrollVertically(DIRECTION_UP) ?: return)
    }
}

让我们向 RecyclerView 添加扩展方法,以轻松将此修复应用于 RV。

fun RecyclerView.fixSwipeToRefresh(refreshLayout: SwipeRefreshLayout): RecyclerViewSwipeToRefresh {
    return RecyclerViewSwipeToRefresh(refreshLayout).also {
        this.addOnScrollListener(it)
    }
}

现在,我们可以使用以下方法修复recyclerView:

recycler_view.apply {
     ...
     fixSwipeToRefresh(swipe_container)
     ...
}

0
投票

以下代码对我有用,请确保将其放置在 binding.recycler_view.setOnRefreshListener{} 方法下方。

 binding.swipeToRefreshLayout.setOnChildScrollUpCallback(object : SwipeRefreshLayout.OnChildScrollUpCallback {
        override fun canChildScrollUp(parent: SwipeRefreshLayout, child: View?): Boolean {
            if (binding.rvDiscover != null) {
                return binding.recyclerView.canScrollVertically(-1)
            }
            return false
        }
    })
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.