PullToRefreshState


The state of a PullToRefreshBox which tracks the distance that the container and indicator have been pulled.

Each instance of PullToRefreshBox should have its own PullToRefreshState.

PullToRefreshState can be used with other progress indicators like so:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.ListItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.pulltorefresh.PullToRefreshState
import androidx.compose.material3.pulltorefresh.pullToRefresh
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier

var itemCount by remember { mutableIntStateOf(15) }
var isRefreshing by remember { mutableStateOf(false) }
val state = rememberPullToRefreshState()
val coroutineScope = rememberCoroutineScope()
val onRefresh: () -> Unit = {
    isRefreshing = true
    coroutineScope.launch {
        // fetch something
        delay(5000)
        itemCount += 5
        isRefreshing = false
    }
}

Scaffold(
    modifier =
        Modifier.pullToRefresh(
            state = state,
            isRefreshing = isRefreshing,
            onRefresh = onRefresh
        ),
    topBar = {
        TopAppBar(
            title = { Text("TopAppBar") },
            // Provide an accessible alternative to trigger refresh.
            actions = {
                IconButton(onClick = onRefresh) {
                    Icon(Icons.Filled.Refresh, "Trigger Refresh")
                }
            }
        )
    }
) {
    Box(Modifier.padding(it)) {
        LazyColumn(Modifier.fillMaxSize()) {
            if (!isRefreshing) {
                items(itemCount) { ListItem({ Text(text = "Item ${itemCount - it}") }) }
            }
        }
        if (isRefreshing) {
            LinearProgressIndicator(modifier = Modifier.fillMaxWidth())
        } else {
            LinearProgressIndicator(
                modifier = Modifier.fillMaxWidth(),
                progress = { state.distanceFraction }
            )
        }
    }
}

Summary

Public functions

suspend Unit

Animate the distance towards the position where the indicator will be hidden when idle

Cmn
suspend Unit

Animate the distance towards the anchor or threshold position, where the indicator will be shown when refreshing.

Cmn
suspend Unit
snapTo(targetValue: @FloatRange(from = 0.0) Float)

Snap the indicator to the desired threshold fraction

Cmn

Public properties

Float

Distance percentage towards the refresh threshold.

Cmn
Boolean

whether the state is currently animating the indicator to the threshold offset, or back to the hidden offset

Cmn

Public functions

animateToHidden

suspend fun animateToHidden(): Unit

Animate the distance towards the position where the indicator will be hidden when idle

animateToThreshold

suspend fun animateToThreshold(): Unit

Animate the distance towards the anchor or threshold position, where the indicator will be shown when refreshing.

snapTo

suspend fun snapTo(targetValue: @FloatRange(from = 0.0) Float): Unit

Snap the indicator to the desired threshold fraction

Public properties

distanceFraction

val distanceFractionFloat

Distance percentage towards the refresh threshold. 0.0 indicates no distance, 1.0 indicates being at the threshold offset, 1.0 indicates overshoot beyond the provided threshold.

isAnimating

val isAnimatingBoolean

whether the state is currently animating the indicator to the threshold offset, or back to the hidden offset