# PullToRefreshState

Artifact: [androidx.wear.compose:compose-material3](https://developer.android.com/jetpack/androidx/releases/wear-compose) [View Source](https://cs.android.com/search?q=file:androidx/wear/compose/material3/PullToRefresh.kt+class:androidx.wear.compose.material3.PullToRefreshState) Added in [1.8.0-alpha03](https://developer.android.com/jetpack/androidx/releases/wear-compose#1.8.0-alpha03)


```
interface PullToRefreshState
```

<br />

*** ** * ** ***

The state of a `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/PullToRefreshBox.composable#PullToRefreshBox(kotlin.Boolean,kotlin.Function0,androidx.wear.compose.material3.PullToRefreshState,androidx.compose.ui.Modifier,androidx.compose.ui.Alignment,kotlin.Function1,kotlin.Boolean,androidx.compose.ui.unit.Dp,kotlin.Function1)` which tracks the distance that the container and indicator have been pulled.

Each instance of `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/PullToRefreshBox.composable#PullToRefreshBox(kotlin.Boolean,kotlin.Function0,androidx.wear.compose.material3.PullToRefreshState,androidx.compose.ui.Modifier,androidx.compose.ui.Alignment,kotlin.Function1,kotlin.Boolean,androidx.compose.ui.unit.Dp,kotlin.Function1)` should have its own `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/PullToRefreshState`.

`https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/PullToRefreshState` can be used with custom progress indicators like so:

```kotlin
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState
import androidx.wear.compose.material3.AppScaffold
import androidx.wear.compose.material3.Button
import androidx.wear.compose.material3.ButtonDefaults
import androidx.wear.compose.material3.CircularProgressIndicator
import androidx.wear.compose.material3.Icon
import androidx.wear.compose.material3.MaterialTheme
import androidx.wear.compose.material3.ProgressIndicatorDefaults
import androidx.wear.compose.material3.PullToRefreshBox
import androidx.wear.compose.material3.PullToRefreshDefaults
import androidx.wear.compose.material3.PullToRefreshState
import androidx.wear.compose.material3.ScreenScaffold
import androidx.wear.compose.material3.SurfaceTransformation
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.TimeText
import androidx.wear.compose.material3.lazy.rememberTransformationSpec
import androidx.wear.compose.material3.lazy.transformedHeight

var isRefreshing by remember { mutableStateOf(false) }
val coroutineScope = rememberCoroutineScope()
val state = remember { PullToRefreshState() }
val listState = rememberTransformingLazyColumnState()
val transformationSpec = rememberTransformationSpec()

AppScaffold {
    ScreenScaffold(scrollState = listState, timeText = { TimeText() }) { contentPadding ->
        PullToRefreshBox(
            isRefreshing = isRefreshing,
            onRefresh = {
                isRefreshing = true
                coroutineScope.launch {
                    delay(2000)
                    isRefreshing = false
                }
            },
            state = state,
            indicator = {
                PullToRefreshDefaults.IndicatorBox(
                    state = state,
                    isRefreshing = isRefreshing,
                    shape = MaterialTheme.shapes.medium,
                    containerColor = MaterialTheme.colorScheme.primaryContainer,
                    modifier = Modifier.align(Alignment.TopCenter),
                ) {
                    if (isRefreshing) {
                        CircularProgressIndicator(
                            strokeWidth = 2.5.dp,
                            colors =
                                ProgressIndicatorDefaults.colors(
                                    indicatorColor =
                                        MaterialTheme.colorScheme.onPrimaryContainer
                                ),
                            modifier = Modifier.size(24.dp),
                        )
                    } else {
                        val rotation = state.distanceFraction * 180f
                        val scale = state.distanceFraction.coerceIn(0f, 1f)
                        Icon(
                            imageVector = Icons.Default.Refresh,
                            contentDescription = "Pull to refresh",
                            tint = MaterialTheme.colorScheme.onPrimaryContainer,
                            modifier =
                                Modifier.size(24.dp).graphicsLayer {
                                    rotationZ = rotation
                                    scaleX = scale
                                    scaleY = scale
                                },
                        )
                    }
                }
            },
            modifier = Modifier.fillMaxSize(),
        ) {
            TransformingLazyColumn(
                state = listState,
                contentPadding = contentPadding,
                modifier = Modifier.fillMaxSize(),
            ) {
                items(10) { index ->
                    Button(
                        onClick = {},
                        label = { Text("Custom item ${index + 1}") },
                        transformation = SurfaceTransformation(transformationSpec),
                        modifier =
                            Modifier.transformedHeight(this, transformationSpec)
                                .minimumVerticalContentPadding(
                                    ButtonDefaults.minimumVerticalListContentPadding
                                )
                                .fillMaxWidth(),
                    )
                }
            }
        }
    }
}
```

## Summary

| ### Public functions |
|---|---|
| `suspend https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/PullToRefreshState#animateToHidden()()` Animate the distance towards the position where the indicator will be hidden when idle. |
| `suspend https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/PullToRefreshState#animateToThreshold()()` Animate the distance towards the anchor or threshold position, where the indicator will be shown when refreshing. |
| `suspend https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/PullToRefreshState#snapTo(kotlin.Float)(targetValue: @https://developer.android.com/reference/kotlin/androidx/annotation/FloatRange(from = 0.0) https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html)` Snap the indicator to the desired threshold fraction. |

| ### Public properties |
|---|---|
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html` | `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/PullToRefreshState#distanceFraction()` Distance percentage towards the refresh threshold. |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html` | `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/PullToRefreshState#isAnimating()` Whether the state is currently animating the indicator to the threshold offset, or back to the hidden offset. |

## Public functions

### animateToHidden

Added in [1.8.0-alpha03](https://developer.android.com/jetpack/androidx/releases/wear-compose#1.8.0-alpha03)

```
suspend fun animateToHidden(): Unit
```

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

### animateToThreshold

Added in [1.8.0-alpha03](https://developer.android.com/jetpack/androidx/releases/wear-compose#1.8.0-alpha03)

```
suspend fun animateToThreshold(): Unit
```

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

### snapTo

Added in [1.8.0-alpha03](https://developer.android.com/jetpack/androidx/releases/wear-compose#1.8.0-alpha03)

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

Snap the indicator to the desired threshold fraction.

| Parameters |
|---|---|
| `targetValue: @https://developer.android.com/reference/kotlin/androidx/annotation/FloatRange(from = 0.0) https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html` | The target fraction to snap to, where 0.0 represents the hidden state and 1.0 represents the threshold position. |

## Public properties

### distanceFraction

Added in [1.8.0-alpha03](https://developer.android.com/jetpack/androidx/releases/wear-compose#1.8.0-alpha03)

```
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.

### isAnimating

Added in [1.8.0-alpha03](https://developer.android.com/jetpack/androidx/releases/wear-compose#1.8.0-alpha03)

```
val isAnimating: Boolean
```

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