![](/img/trans.png)
[英]Pull SwipeRefreshLayout to refresh RecyclerView In Fragment in android but Not Working
[英]Scrolling SwipeRefreshLayout with RecyclerView Refresh anywhere in android 2.2
我的布局有问题,我在里面创建了带有 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但没有解决方案。 知道如何解决吗?
覆盖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();
不幸的是,这是一个已知问题,将在未来版本中修复。
https://code.google.com/p/android/issues/detail?id=78191
同时,如果您需要紧急修复, canChildScrollUp
在SwipeRefreshLayout.java
覆盖SwipeRefreshLayout.java
并调用recyclerView.canScrollVertically(mTarget, -1)
。 因为在姜饼之后添加了canScrollVertically
,所以您还需要复制该方法并在recyclerview中实现。
或者,如果您使用的是LinearLayoutManager,则可以调用findFirstCompletelyVisibleItemPosition
。
抱歉给你带来不便。
我使用以下代码修复了向上滚动问题:
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
具体取决于您是否有一个或多个侦听器。
您可以根据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)));
}
}
您可以在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);
}
}
基于@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)
...
}
以下代码对我有用,请确保它位于 binding.refreshDiscoverList.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
}
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.