PullToRefreshState

Interface

Common
@ExperimentalMaterial3Api
interface 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:

Properties

Common
@get:FloatRange(from = 0.0) val distanceFraction: Float

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.

Common
val isAnimating: Boolean

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

Functions

suspend fun animateToThreshold()

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

suspend fun animateToHidden()

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

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

Snap the indicator to the desired threshold fraction

Code Examples

PullToRefreshLinearProgressIndicatorSample

@Composable
@Preview
@OptIn(ExperimentalMaterial3Api::class)
fun PullToRefreshLinearProgressIndicatorSample() {
    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 },
                )
            }
        }
    }
}