You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复视图可见/隐藏切换时SwipeRefreshLayout无法正常下拉刷新的问题

问题根因

你遇到的问题根源有两个:

  1. SwipeRefreshLayout默认只有当内部直接子View可滚动时,才会响应下拉手势。当你把RecyclerView设为GONE/INVISIBLE后,SwipeRefreshLayout判定内部没有可滚动的内容,不会处理触摸事件。
  2. 你的空态视图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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 09:12:07