スクロールできないItem数でSwipeRefreshLayoutがうまく動かない時

SwipeRefreshLayoutとRecyclerViewを使って縦に要素を並べてスクロールさせる時を想定している。 要素数が3,4つなどスクロールするには満たない時にSwipeRefreshLayoutのOnRefreshListener.onRefreshが呼ばれないことがあったのでメモ。 RecyclerViewへのアイテム追加はGroupieを使用している。

修正前のxml
 <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
            android:id="@+id/refresh_V"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

                <androidx.recyclerview.widget.RecyclerView
                    android:id="@+id/recycler_view"
                    android:layout_width="0dp"
                    android:layout_height="0dp"
                    app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />
        </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

このxmlを使うと、 - 要素数が0の時はonRefreshが呼ばれindicatorが表示される。 - 要素数が1などスクロールに満たない時、onRefreshが呼ばれない。 - 要素数がスクロールできる高さ分ある時、onRefresh が呼ばれindicatorが表示される。

修正後のxml

スクロールに満たない要素数でもonRefreshが呼ばれるケースと比較していった結果、RecyclerViewをConstraintLayoutで囲うことで、要素数がスクロールに満たない場合でもonRefresh が呼ばれることを確認できた。

  <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
            android:id="@+id/refresh_V"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">


            <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <androidx.recyclerview.widget.RecyclerView
                    android:id="@+id/recycler_view"
                    android:layout_width="0dp"
                    android:layout_height="0dp"
                    app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />

            </androidx.constraintlayout.widget.ConstraintLayout>
        </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

詳しい理由はよくわからず。同じ問題の他の記事も自分の範囲だと見当たらなかったので、何か他に発生する条件があるのかもしれない。 一見普通に動いているように見えたので、今後同じ問題に出逢った場合は気をつけたい。 SwipeRefreshLayout  |  Android Developers