LoginSignup
4
4

【Android】驚くほどシンプルなComposeのPullToRefreshを実装してみた

Posted at

はじめに

皆さん、ごきげんよう!れぶです!

今回の記事では、Composeのリスト表示でPullToRefresh機能を実装してみたので、その手順をサクッと解説していきます。

PullToRefreshで表示するデータを更新したい方には特に参考になるのではないかと思います。

約5分以内で読めます。それでは、参りましょう!!

開発環境

  • MacBook Air
  • Android Studio Hedgehog | 2023.1.1 Canary 9
  • Kotlin
  • compileSdkVersion 34
  • minSdkVersion 24

動作イメージ

動画のように、PullToRefreshで毎回ランダムな数字をリスト表示するという超シンプルなものです。ただし、初回読み込み時はPullToRefreshのインジケーターは表示されないようにしています。

ezgif.com-video-to-gif.gif

実装手順

1.依存関係を追加

build.gradle(app)
dependencies {
    implementation "androidx.compose.material:material:latest-version"
}

今回はcompose.materialのPullToRefreshを使用します。以下は補足です。

  • 現時点でAccompanistライブラリのSwipe Refreshは非推奨
  • 現時点でmaterial3公式のPullToRefreshはリリースされていない

2.ViewModelの作成

NumberViewModel.kt
class NumberViewModel : ViewModel() {
    private val _numbers = MutableStateFlow<List<Int>>(listOf())
    val numbers: StateFlow<List<Int>> = _numbers

    private val _isRefreshing = MutableStateFlow(false)
    val isRefreshing: StateFlow<Boolean> = _isRefreshing

    init {
        initializeNumbers()
    }

    //初期化時
    private fun initializeNumbers() {
        updateNumbers()
    }

    //PullToRefresh時
    fun refreshNumbers() {
        updateNumbers(isRefreshing = true)
    }

    //共通処理
    private fun updateNumbers(isRefreshing: Boolean = false) {
        viewModelScope.launch {
            if (isRefreshing) {
                _isRefreshing.emit(true)
            }

            val newList = List(5) { Random.nextInt(100) }
            _numbers.emit(newList)
            delay(1000)

            _isRefreshing.emit(false)
        }
    }
}

このViewModelでは、リストデータとPullToRefreshの状態の管理を担当します。

今回は初回読み込み時とPullToRefresh時とで処理を分岐させていますが、共通処理はupdateNumbers()でまとめています。

3.UIとの繋ぎ込み

Compose.kt
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun SwipeRefreshSample(
    modifier: Modifier = Modifier,
    viewModel: NumberViewModel = viewModel()
) {
    val numbers by viewModel.numbers.collectAsState()
    val isRefreshing by viewModel.isRefreshing.collectAsState()

    val state = rememberPullRefreshState(
        refreshing = isRefreshing,
        onRefresh = { viewModel.refreshNumbers() }
    )

    Box(modifier = modifier.pullRefresh(state)) {
        LazyColumn(
            modifier = Modifier.fillMaxWidth()
        ) {
            items(numbers) { number ->
                Text(
                    text = "Number: $number",
                    fontSize = 20.sp,
                    modifier = Modifier.padding(bottom = 10.dp),
                )
            }
        }

        PullRefreshIndicator(
            refreshing = isRefreshing,
            state = state,
            modifier = Modifier.align(Alignment.TopCenter)
        )
    }
}

このComposable関数では、上記で作成したViewModelをもとにPullToRefreshによって毎回数字リストをランダムに更新して表示しています。

対象レイアウトをBox(Modifier.pullRefresh(state))で囲み、PullToRefresh機能を統合します。pullRefresh()の引数には、rememberPullRefreshState関数を用いて更新状態を管理するStateを入れます。

また、PullRefreshIndicatorで更新中のインジケータ(くるくる回る矢印)の表示を制御します。関数の第一引数には先ほどのState、第二引数にはViewModelで定義した更新状態を入れます。

サンプルコード

おわりに

今回はJetpack Composeを使って、PullToRefresh機能を備えたリスト表示の実装手順を簡単に整理していきました。「意外と簡単じゃん」って感じた方も少なくないと思います。

要は、表示データと更新状態を管理するViewModelを元にComposeに落とし込めば楽勝なのです。PullToRefresh自体はModifierで指定するので、馴染み深いかと思います。

この記事がComposeで更新機能を作る方に少しでも役立つと嬉しいです。ありがとうございました😎

参考サイト

参考にしたChatGPTの会話

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4