画面の状態を最新にするのにリストを下にスクロールして更新するUIがモバイルアプリではよく使われますがRecyclerViewとSwipeRefreshLayoutを使うと簡単に実装できます。

RecyclerViewがあるモジュールのbuild.gradle.ktsに下記を追加します。(バージョンは2023年1月時点で最新のバージョン)

dependencies {
    implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
}

レイアウトXMLファイルでSwipeRefreshLayoutの下にRecyclerViewがあるようにします。

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/swipe_refresh_layout"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:scrollbars="vertical"
            android:fadeScrollbars="false"
            android:scrollbarThumbVertical="?attr/colorPrimary"
            android:scrollbarSize="4dp"
            android:scrollbarStyle="outsideInset"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

ViewBindingのファイル名は適宜読み替えてください。FragmentにOnRefreshListenerを継承するようにしてoverride fun onRefresh() {}の中身を実装します。

@AndroidEntryPoint
class MyFragment : Fragment(), OnRefreshListener {
    private var _fragmentBinding: FragmentBinding? = null
    private val fragmentBinding get() = _fragmentBinding!!

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _fragmentBinding = FragmentBinding.inflate(layoutInflater, container, false)
        return fragmentBinding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        fragmentBinding.swipeRefreshLayout.apply {
            setOnRefreshListener(this@MyFragment)
            setColorSchemeColors(requireContext().getColor(R.color.infoColor)) // 引っ張った時のアイコンの色を変更する場合はここで色を設定する
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()

        _fragmentBinding = null
    }

    override fun onRefresh() {
 
                // 画面の内容を最新に更新する処理
 
        fragmentBinding.swipeRefreshLayout.isRefreshing = false // 画面の表示が完了したらisRefreshing = falseにする
    }
}

すごく簡単ですね。