PullToRefresh
PullToRefresh is a pull-to-refresh component in COUI that provides refresh functionality for lists and other scrollable content. It features an animated interactive refresh indicator suitable for various scenarios where data refresh is needed.
WARNING
This component is only available in touch-enabled environments.
Import
import io.github.suqi8.coui.kmp.basic.PullToRefresh
import io.github.suqi8.coui.kmp.basic.rememberPullToRefreshStateBasic Usage
PullToRefresh can wrap any scrollable content:
var isRefreshing by rememberSaveable { mutableStateOf(false) }
val pullToRefreshState = rememberPullToRefreshState()
var items by remember { mutableStateOf(1) }
LaunchedEffect(isRefreshing) {
if (isRefreshing) {
delay(500)
items += 6
isRefreshing = false
}
}
Surface {
PullToRefresh(
isRefreshing = isRefreshing,
onRefresh = { isRefreshing = true },
pullToRefreshState = pullToRefreshState,
) {
LazyColumn(
modifier = Modifier.fillMaxSize()
) {
items(items) { index ->
ArrowPreference(
title = "Item $index",
modifier = Modifier.padding(horizontal = 16.dp),
onClick = { /* Click event */ }
)
}
}
}
}Contract for isRefreshing
isRefreshing is the hoisted source of truth for the refresh operation. Set it to true in onRefresh when the gesture triggers a refresh, and set it back to false when the data loading completes — lowering it ends the refresh and plays the completion animation. The indicator itself is shown by the pull gesture; PullToRefreshState only manages the visual state.
Component States
PullToRefresh has the following states:
Idle: Initial state, no interactionPulling: User is pulling but hasn't reached the refresh thresholdThresholdReached: Pull threshold reached, release to refreshRefreshing: Currently refreshingRefreshComplete: Refresh completed, returning to initial state
Properties
PullToRefresh Properties
| Property Name | Type | Description | Default Value | Required |
|---|---|---|---|---|
| isRefreshing | Boolean | Refresh state | None | Yes |
| onRefresh | () -> Unit | Refresh callback function | None | Yes |
| modifier | Modifier | Container modifier | Modifier | No |
| pullToRefreshState | PullToRefreshState | PullToRefresh state | rememberPullToRefreshState() | No |
| contentPadding | PaddingValues | Content padding | PaddingValues(0.dp) | No |
| topAppBarScrollBehavior | ScrollBehavior | Top app bar scroll behavior | null | No |
| color | Color | Indicator color (Unspecified falls back to theme primary) | PullToRefreshDefaults.color | No |
| circleSize | Dp | Indicator circle size | PullToRefreshDefaults.circleSize | No |
| refreshTexts | List<String> | Text list for different states | PullToRefreshDefaults.refreshTexts | No |
| refreshTextStyle | TextStyle | Refresh text style | PullToRefreshDefaults.refreshTextStyle | No |
| content | @Composable () -> Unit | Scrollable content composable | None | Yes |
PullToRefreshState Class
PullToRefreshState manages the UI state of the refresh indicator and can be created using rememberPullToRefreshState() (which takes no parameters). It should only be used for UI state, while refresh logic should be controlled by isRefreshing and onRefresh.
| Property Name | Type | Description |
|---|---|---|
| refreshState | RefreshState | Current visual refresh state |
| pullProgress | Float | Pull progress (0-1) relative to the refresh trigger threshold |
| dragOffset | Float | The current drag offset in pixels |
PullToRefreshDefaults Object
PullToRefreshDefaults provides default values for the component.
| Property Name | Type | Description | Default Value |
|---|---|---|---|
| color | Color | Default indicator color | Color.Unspecified (falls back to the theme primary color) |
| circleSize | Dp | Default indicator size | 19.dp |
| refreshTexts | List<String> | Default text list | ["Pull down to refresh", "Release to refresh", "Refreshing...", "Refreshed successfully"] |
| refreshTextStyle | TextStyle | Default text style | TextStyle(fontSize = 14.sp, fontWeight = Bold, color = color) |
Advanced Usage
Custom Indicator Color
PullToRefresh(
color = Color.Blue,
// Other properties
) {
// Content
}Custom Refresh Texts
PullToRefresh(
refreshTexts = listOf(
"Pull to refresh",
"Release to refresh",
"Refreshing",
"Refresh successful",
),
// Other properties
) {
// Content
}Coordinating with a TopAppBar
Pass the TopAppBar scroll behavior so the app bar and the pull gesture share nested scroll events:
val scrollBehavior = COUIScrollBehavior()
PullToRefresh(
isRefreshing = isRefreshing,
onRefresh = { isRefreshing = true },
topAppBarScrollBehavior = scrollBehavior,
) {
// Scrollable content
}
