如何修复视图可见/隐藏切换时SwipeRefreshLayout无法正常下拉刷新的问题
问题根因
你遇到的问题根源有两个:
- SwipeRefreshLayout默认只有当内部直接子View可滚动时,才会响应下拉手势。当你把RecyclerView设为GONE/INVISIBLE后,SwipeRefreshLayout判定内部没有可滚动的内容,不会处理触摸事件。
- 你的空态视图
vErrorStateNotification层级在SwipeRefreshLayout上方,触摸事件会被空态视图优先消费,不会传递到下方的SwipeRefreshLayout。
方案1:调整布局结构(推荐)
把空态视图放到SwipeRefreshLayout内部,和RecyclerView平级,修改后XML如下:
<FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <androidx.swiperefreshlayout.widget.SwipeRefreshLayout android:id="@+id/vSwipeToRefreshNotification" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/rvNotificationItems" android:layout_width="match_parent" android:layout_height="match_parent" android:clipToPadding="false" android:paddingTop="@dimen/spacing_16" android:paddingBottom="@dimen/spacing_72" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" tools:listitem="@layout/layout_list_item_notification" /> <com.example.deepdiveandroid.base.ui.view.FullScreenErrorStateView android:id="@+id/vErrorStateNotification" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" /> </FrameLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </LinearLayout> </FrameLayout>
调整后,空态视图和RecyclerView都在SwipeRefreshLayout的管辖范围内,下拉手势会被SwipeRefreshLayout正常捕获,不需要修改原有显隐逻辑,列表为空时直接显示空态、隐藏RecyclerView即可。
方案2:强制SwipeRefreshLayout响应下拉
如果不想调整布局,可以给SwipeRefreshLayout设置滚动判断回调,当列表为空时强制允许触发下拉,代码示例:
Kotlin版:
vSwipeToRefreshNotification.setOnChildScrollUpCallback { _, _ -> // 列表为空时返回false,允许触发下拉;列表不为空时走默认逻辑 if (rvNotificationItems.adapter?.itemCount == 0) { false } else { rvNotificationItems.canScrollVertically(-1) } }
Java版:
vSwipeToRefreshNotification.setOnChildScrollUpCallback(new SwipeRefreshLayout.OnChildScrollUpCallback() { @Override public boolean canChildScrollUp(@NonNull SwipeRefreshLayout parent, @Nullable View child) { if (rvNotificationItems.getAdapter() == null || rvNotificationItems.getAdapter().getItemCount() == 0) { return false; } return rvNotificationItems.canScrollVertically(-1); } });
同时需要给空态视图设置android:clickable="false",避免触摸事件被空态拦截。
内容的提问来源于stack exchange,提问作者chrisu.chrisu
相关产品推荐
相关产品推荐

