Tarik untuk me-refresh

Komponen tarik untuk memperbarui memungkinkan pengguna menarik ke bawah di awal konten aplikasi untuk memperbarui data.

Platform API

Gunakan composable PullToRefreshBox untuk menerapkan tarik lalu muat ulang, yang bertindak sebagai penampung untuk konten yang dapat di-scroll. Parameter utama berikut mengontrol perilaku dan tampilan pembaruan:

  • isRefreshing: Nilai boolean yang menunjukkan apakah tindakan refresh sedang berlangsung.
  • onRefresh: Fungsi lambda yang dijalankan saat pengguna memulai refresh.
  • indicator: Menyesuaikan indikator yang digambar sistem pada tarik untuk memperbarui.

Contoh dasar

Cuplikan ini menunjukkan penggunaan dasar PullToRefreshBox:

@Composable
fun PullToRefreshBasicSample(
    items: List<String>,
    isRefreshing: Boolean,
    onRefresh: () -> Unit,
    modifier: Modifier = Modifier
) {
    PullToRefreshBox(
        isRefreshing = isRefreshing,
        onRefresh = onRefresh,
        modifier = modifier
    ) {
        LazyColumn(Modifier.fillMaxSize()) {
            items(items) {
                ListItem({ Text(text = it) })
            }
        }
    }
}

Poin penting tentang kode

  • PullToRefreshBox membungkus LazyColumn, yang menampilkan daftar string.
  • PullToRefreshBox memerlukan parameter isRefreshing dan onRefresh.
  • Konten dalam blok PullToRefreshBox merepresentasikan konten yang dapat di-scroll.

Hasil

Video ini menunjukkan implementasi tarik lalu muat ulang dasar dari kode sebelumnya:

Gambar 1. Implementasi tarik untuk memperbarui dasar pada daftar item.

Contoh lanjutan: Menyesuaikan warna indikator

@Composable
fun PullToRefreshCustomStyleSample(
    items: List<String>,
    isRefreshing: Boolean,
    onRefresh: () -> Unit,
    modifier: Modifier = Modifier
) {
    val state = rememberPullToRefreshState()

    PullToRefreshBox(
        isRefreshing = isRefreshing,
        onRefresh = onRefresh,
        modifier = modifier,
        state = state,
        indicator = {
            Indicator(
                modifier = Modifier.align(Alignment.TopCenter),
                isRefreshing = isRefreshing,
                containerColor = MaterialTheme.colorScheme.primaryContainer,
                color = MaterialTheme.colorScheme.onPrimaryContainer,
                state = state
            )
        },
    ) {
        LazyColumn(Modifier.fillMaxSize()) {
            items(items) {
                ListItem({ Text(text = it) })
            }
        }
    }
}

Poin penting tentang kode

  • Warna indikator disesuaikan melalui properti containerColor dan color dalam parameter indicator.
  • rememberPullToRefreshState() mengelola status tindakan refresh. Anda menggunakan status ini bersama dengan parameter indicator.

Hasil

Video ini menunjukkan implementasi tarik untuk memuat ulang dengan indikator berwarna:

Gambar 2. Implementasi tarik untuk memuat ulang dengan gaya kustom.

Contoh lanjutan: Membuat indikator yang sepenuhnya disesuaikan

Anda dapat membuat indikator kustom yang kompleks dengan memanfaatkan composable dan animasi yang ada.Cuplikan ini menunjukkan cara membuat indikator yang sepenuhnya kustom dalam implementasi tarik untuk memperbarui:

@Composable
fun PullToRefreshCustomIndicatorSample(
    items: List<String>,
    isRefreshing: Boolean,
    onRefresh: () -> Unit,
    modifier: Modifier = Modifier
) {
    val state = rememberPullToRefreshState()

    PullToRefreshBox(
        isRefreshing = isRefreshing,
        onRefresh = onRefresh,
        modifier = modifier,
        state = state,
        indicator = {
            MyCustomIndicator(
                state = state,
                isRefreshing = isRefreshing,
                modifier = Modifier.align(Alignment.TopCenter)
            )
        }
    ) {
        LazyColumn(Modifier.fillMaxSize()) {
            items(items) {
                ListItem({ Text(text = it) })
            }
        }
    }
}

// ...
@Composable
fun MyCustomIndicator(
    state: PullToRefreshState,
    isRefreshing: Boolean,
    modifier: Modifier = Modifier,
) {
    Box(
        modifier = modifier.pullToRefreshIndicator(
            state = state,
            isRefreshing = isRefreshing,
            containerColor = PullToRefreshDefaults.containerColor,
            threshold = PositionalThreshold
        ),
        contentAlignment = Alignment.Center
    ) {
        Crossfade(
            targetState = isRefreshing,
            animationSpec = tween(durationMillis = CROSSFADE_DURATION_MILLIS),
            modifier = Modifier.align(Alignment.Center)
        ) { refreshing ->
            if (refreshing) {
                CircularProgressIndicator(Modifier.size(SPINNER_SIZE))
            } else {
                val distanceFraction = { state.distanceFraction.coerceIn(0f, 1f) }
                Icon(
                    imageVector = Icons.Filled.CloudDownload,
                    contentDescription = "Refresh",
                    modifier = Modifier
                        .size(18.dp)
                        .graphicsLayer {
                            val progress = distanceFraction()
                            this.alpha = progress
                            this.scaleX = progress
                            this.scaleY = progress
                        }
                )
            }
        }
    }
}

Poin penting tentang kode

  • Cuplikan sebelumnya menggunakan Indicator yang disediakan oleh library. Cuplikan ini membuat composable indikator kustom yang disebut MyCustomIndicator. Dalam composable ini, pengubah pullToRefreshIndicator menangani pemosisian dan pemicuan refresh.
  • Seperti pada cuplikan sebelumnya, contoh ini mengekstrak instance PullToRefreshState, sehingga Anda dapat meneruskan instance yang sama ke PullToRefreshBox dan pullToRefreshModifier.
  • Contoh ini menggunakan warna penampung dan nilai minimum posisi dari class PullToRefreshDefaults. Dengan begitu, Anda dapat menggunakan kembali perilaku dan gaya default dari library Material, sambil menyesuaikan hanya elemen yang Anda inginkan.
  • MyCustomIndicator menggunakan Crossfade untuk bertransisi antara ikon cloud dan CircularProgressIndicator. Ikon cloud akan diperbesar saat pengguna menarik, dan bertransisi ke CircularProgressIndicator saat tindakan refresh dimulai.
    • targetState menggunakan isRefreshing untuk menentukan status mana yang akan ditampilkan (ikon cloud atau indikator progres melingkar).
    • animationSpec menentukan animasi tween untuk transisi, dengan durasi yang ditentukan sebesar CROSSFADE_DURATION_MILLIS.
    • state.distanceFraction menunjukkan seberapa jauh pengguna telah menarik ke bawah, mulai dari 0f (tidak ditarik) hingga 1f (ditarik sepenuhnya).
    • Pengubah graphicsLayer mengubah skala dan transparansi.

Hasil

Video ini menampilkan indikator kustom dari kode sebelumnya:

Gambar 3. Implementasi tarik untuk memuat ulang dengan indikator kustom.

Referensi lainnya