xref: /aosp_15_r20/external/accompanist/docs/swiperefresh.md (revision fa44fe6ae8e729aa3cfe5c03eedbbf98fb44e2c6)
1# Swipe Refresh for Jetpack Compose
2
3[![Maven Central](https://img.shields.io/maven-central/v/com.google.accompanist/accompanist-swiperefresh)](https://search.maven.org/search?q=g:com.google.accompanist)
4
5!!! warning
6    **This library is deprecated, with official pull refresh support in [androidx.compose.material.pullrefresh](https://developer.android.com/reference/kotlin/androidx/compose/material/pullrefresh/package-summary).** The migration guide and original documentation is below.
7
8## Migration
9
10Accompanist SwipeRefresh has been replaced by PullRefresh in [Compose Material 1.3.0](https://developer.android.com/jetpack/androidx/releases/compose-material#1.3.0). The implementation is similar but instead of being a Composable function, it is a Modifier that can be applied to a Composable function.
11
12A simple example is as follows:
13
14```kotlin
15val viewModel: MyViewModel = viewModel()
16val refreshing by viewModel.isRefreshing
17
18val pullRefreshState = rememberPullRefreshState(refreshing, { viewModel.refresh() })
19
20Box(Modifier.pullRefresh(pullRefreshState)) {
21    LazyColumn(Modifier.fillMaxSize()) {
22        ...
23    }
24
25    PullRefreshIndicator(refreshing, pullRefreshState, Modifier.align(Alignment.TopCenter))
26}
27```
28
29### Migration steps
30
311. Replace SwipeRefresh with a Box or other layout of your choice, save your `onRefresh` lambda for the next step.
322. Replace `rememberSwipeRefreshState()` with `rememberPullRefreshState(refreshing, onRefresh)`
333. Add either the default `PullRefreshIndicator` or your own custom implementation to your layout.
34
35### Custom Indicator
36
37Instead of using the provided `PullRefreshIndicator` composable, you can create your own custom indicator.
38A full sample can be seen in the [Compose samples](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/material/material/samples/src/main/java/androidx/compose/material/samples/PullRefreshSamples.kt;l=91?q=pullrefresh).
39
40## Original Docs
41
42A library which provides a layout which provides the swipe-to-refresh UX pattern, similar to Android's [`SwipeRefreshLayout`](https://developer.android.com/training/swipe/add-swipe-interface).
43
44<figure>
45    <video width="400" controls loop>
46    <source src="demo.mp4" type="video/mp4">
47        Your browser does not support the video tag.
48    </video>
49    <figcaption>SwipeRefresh demo</figcaption>
50</figure>
51
52## Usage
53
54To implement this UX pattern there are two key APIs which are needed: [`SwipeRefresh`][api_swiperefresh], which is provides the layout, and [`rememberSwipeRefreshState()`][api_rememberstate] which provides some remembered state.
55
56The basic usage of a [`SwipeRefresh`][api_swiperefresh] using a ViewModel looks like so:
57
58``` kotlin
59val viewModel: MyViewModel = viewModel()
60val isRefreshing by viewModel.isRefreshing.collectAsState()
61
62SwipeRefresh(
63    state = rememberSwipeRefreshState(isRefreshing),
64    onRefresh = { viewModel.refresh() },
65) {
66    LazyColumn {
67        items(30) { index ->
68            // TODO: list items
69        }
70    }
71}
72```
73
74The full example, including the view model implementation can be found [here](https://github.com/google/accompanist/blob/main/sample/src/main/java/com/google/accompanist/sample/swiperefresh/DocsSamples.kt).
75
76The content needs to be 'vertically scrollable' for `SwipeRefresh()` to be able to react to swipe gestures. Layouts such as [`LazyColumn`][lazycolumn] are automatically vertically scrollable, but others such as [`Column`][column] or [`LazyRow`][lazyrow] are not. In those instances, you can provide a [`Modifier.verticalScroll`][verticalscroll] modifier to that content like so:
77
78``` kotlin
79SwipeRefresh(
80    // ...
81) {
82    Column(Modifier.verticalScroll(rememberScrollState())) {
83        // content
84    }
85}
86```
87
88
89### Indicating a refresh without swiping
90
91As this library is built with a separate state object, it's easy to display a refreshing indicator without a swipe to triggering it.
92
93The unrealistic example below displays a forever refreshing indicator:
94
95``` kotlin
96val swipeRefreshState = rememberSwipeRefreshState(true)
97
98SwipeRefresh(
99    state = swipeRefreshState,
100    onRefresh = { /* todo */ },
101) {
102    LazyColumn {
103        items(30) { index ->
104            // TODO: list items
105        }
106    }
107}
108```
109
110## Indicator
111
112The library provides a default indicator: [`SwipeRefreshIndicator()`][api_swiperefreshindicator], which `SwipeRefresh` uses automatically. You can customize the default indicator, and even provide your own indicator content using the `indicator` slot.
113
114### Customizing default indicator
115
116To customize the default indicator, we can provide our own `indicator` content block, to call [`SwipeRefreshIndicator()`][api_swiperefreshindicator] with customized parameters:
117
118=== "Sample"
119
120    ``` kotlin
121    SwipeRefresh(
122        state = /* ... */,
123        onRefresh = /* ... */,
124        indicator = { state, trigger ->
125            SwipeRefreshIndicator(
126                // Pass the SwipeRefreshState + trigger through
127                state = state,
128                refreshTriggerDistance = trigger,
129                // Enable the scale animation
130                scale = true,
131                // Change the color and shape
132                backgroundColor = MaterialTheme.colors.primary,
133                shape = MaterialTheme.shapes.small,
134            )
135        }
136    )
137    ```
138
139=== "Demo video"
140
141    <figure>
142        <video width="480" controls loop>
143        <source src="tweaked.mp4" type="video/mp4">
144            Your browser does not support the video tag.
145        </video>
146        <figcaption>Tweaked indicator demo</figcaption>
147    </figure>
148
149### Custom indicator
150
151As mentioned, you can also provide your own custom indicator content. A [`SwipeRefreshState`][api_swiperefreshstate] is provided to `indicator` content slot, which contains the information necessary to react to a swipe refresh gesture.
152
153An example of a custom indicator is provided [here][sample_customindicator].
154
155## Download
156
157[![Maven Central](https://img.shields.io/maven-central/v/com.google.accompanist/accompanist-swiperefresh)](https://search.maven.org/search?q=g:com.google.accompanist)
158
159```groovy
160repositories {
161    mavenCentral()
162}
163
164dependencies {
165    implementation "com.google.accompanist:accompanist-swiperefresh:<version>"
166}
167```
168
169Snapshots of the development version are available in [Sonatype's `snapshots` repository][snap]. These are updated on every commit.
170
171  [compose]: https://developer.android.com/jetpack/compose
172  [snap]: https://oss.sonatype.org/content/repositories/snapshots/com/google/accompanist/accompanist-swiperefresh/
173  [api_swiperefreshstate]: ../api/swiperefresh/com.google.accompanist.swiperefresh/-swipe-refresh-state/
174  [api_swiperefreshindicator]: ../api/swiperefresh/com.google.accompanist.swiperefresh/-swipe-refresh-indicator.html
175  [api_swiperefresh]: ../api/swiperefresh/com.google.accompanist.swiperefresh/-swipe-refresh.html
176  [api_rememberstate]: ../api/swiperefresh/com.google.accompanist.swiperefresh/remember-swipe-refresh-state.html
177  [sample_customindicator]: https://github.com/google/accompanist/blob/main/sample/src/main/java/com/google/accompanist/sample/swiperefresh/SwipeRefreshCustomIndicatorSample.kt
178  [lazycolumn]: https://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyColumn(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Function1)
179  [column]: https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Column(androidx.compose.ui.Modifier,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,kotlin.Function1)
180  [lazyrow]: https://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyRow(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.ui.Alignment.Vertical,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Function1)
181  [verticalscroll]: https://developer.android.com/jetpack/compose/gestures#scroll-modifiers
182