1*fa44fe6aSInna Palant# Swipe Refresh for Jetpack Compose 2*fa44fe6aSInna Palant 3*fa44fe6aSInna Palant[](https://search.maven.org/search?q=g:com.google.accompanist) 4*fa44fe6aSInna Palant 5*fa44fe6aSInna Palant!!! warning 6*fa44fe6aSInna Palant **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*fa44fe6aSInna Palant 8*fa44fe6aSInna Palant## Migration 9*fa44fe6aSInna Palant 10*fa44fe6aSInna PalantAccompanist 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*fa44fe6aSInna Palant 12*fa44fe6aSInna PalantA simple example is as follows: 13*fa44fe6aSInna Palant 14*fa44fe6aSInna Palant```kotlin 15*fa44fe6aSInna Palantval viewModel: MyViewModel = viewModel() 16*fa44fe6aSInna Palantval refreshing by viewModel.isRefreshing 17*fa44fe6aSInna Palant 18*fa44fe6aSInna Palantval pullRefreshState = rememberPullRefreshState(refreshing, { viewModel.refresh() }) 19*fa44fe6aSInna Palant 20*fa44fe6aSInna PalantBox(Modifier.pullRefresh(pullRefreshState)) { 21*fa44fe6aSInna Palant LazyColumn(Modifier.fillMaxSize()) { 22*fa44fe6aSInna Palant ... 23*fa44fe6aSInna Palant } 24*fa44fe6aSInna Palant 25*fa44fe6aSInna Palant PullRefreshIndicator(refreshing, pullRefreshState, Modifier.align(Alignment.TopCenter)) 26*fa44fe6aSInna Palant} 27*fa44fe6aSInna Palant``` 28*fa44fe6aSInna Palant 29*fa44fe6aSInna Palant### Migration steps 30*fa44fe6aSInna Palant 31*fa44fe6aSInna Palant1. Replace SwipeRefresh with a Box or other layout of your choice, save your `onRefresh` lambda for the next step. 32*fa44fe6aSInna Palant2. Replace `rememberSwipeRefreshState()` with `rememberPullRefreshState(refreshing, onRefresh)` 33*fa44fe6aSInna Palant3. Add either the default `PullRefreshIndicator` or your own custom implementation to your layout. 34*fa44fe6aSInna Palant 35*fa44fe6aSInna Palant### Custom Indicator 36*fa44fe6aSInna Palant 37*fa44fe6aSInna PalantInstead of using the provided `PullRefreshIndicator` composable, you can create your own custom indicator. 38*fa44fe6aSInna PalantA 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*fa44fe6aSInna Palant 40*fa44fe6aSInna Palant## Original Docs 41*fa44fe6aSInna Palant 42*fa44fe6aSInna PalantA 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*fa44fe6aSInna Palant 44*fa44fe6aSInna Palant<figure> 45*fa44fe6aSInna Palant <video width="400" controls loop> 46*fa44fe6aSInna Palant <source src="demo.mp4" type="video/mp4"> 47*fa44fe6aSInna Palant Your browser does not support the video tag. 48*fa44fe6aSInna Palant </video> 49*fa44fe6aSInna Palant <figcaption>SwipeRefresh demo</figcaption> 50*fa44fe6aSInna Palant</figure> 51*fa44fe6aSInna Palant 52*fa44fe6aSInna Palant## Usage 53*fa44fe6aSInna Palant 54*fa44fe6aSInna PalantTo 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*fa44fe6aSInna Palant 56*fa44fe6aSInna PalantThe basic usage of a [`SwipeRefresh`][api_swiperefresh] using a ViewModel looks like so: 57*fa44fe6aSInna Palant 58*fa44fe6aSInna Palant``` kotlin 59*fa44fe6aSInna Palantval viewModel: MyViewModel = viewModel() 60*fa44fe6aSInna Palantval isRefreshing by viewModel.isRefreshing.collectAsState() 61*fa44fe6aSInna Palant 62*fa44fe6aSInna PalantSwipeRefresh( 63*fa44fe6aSInna Palant state = rememberSwipeRefreshState(isRefreshing), 64*fa44fe6aSInna Palant onRefresh = { viewModel.refresh() }, 65*fa44fe6aSInna Palant) { 66*fa44fe6aSInna Palant LazyColumn { 67*fa44fe6aSInna Palant items(30) { index -> 68*fa44fe6aSInna Palant // TODO: list items 69*fa44fe6aSInna Palant } 70*fa44fe6aSInna Palant } 71*fa44fe6aSInna Palant} 72*fa44fe6aSInna Palant``` 73*fa44fe6aSInna Palant 74*fa44fe6aSInna PalantThe 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*fa44fe6aSInna Palant 76*fa44fe6aSInna PalantThe 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*fa44fe6aSInna Palant 78*fa44fe6aSInna Palant``` kotlin 79*fa44fe6aSInna PalantSwipeRefresh( 80*fa44fe6aSInna Palant // ... 81*fa44fe6aSInna Palant) { 82*fa44fe6aSInna Palant Column(Modifier.verticalScroll(rememberScrollState())) { 83*fa44fe6aSInna Palant // content 84*fa44fe6aSInna Palant } 85*fa44fe6aSInna Palant} 86*fa44fe6aSInna Palant``` 87*fa44fe6aSInna Palant 88*fa44fe6aSInna Palant 89*fa44fe6aSInna Palant### Indicating a refresh without swiping 90*fa44fe6aSInna Palant 91*fa44fe6aSInna PalantAs this library is built with a separate state object, it's easy to display a refreshing indicator without a swipe to triggering it. 92*fa44fe6aSInna Palant 93*fa44fe6aSInna PalantThe unrealistic example below displays a forever refreshing indicator: 94*fa44fe6aSInna Palant 95*fa44fe6aSInna Palant``` kotlin 96*fa44fe6aSInna Palantval swipeRefreshState = rememberSwipeRefreshState(true) 97*fa44fe6aSInna Palant 98*fa44fe6aSInna PalantSwipeRefresh( 99*fa44fe6aSInna Palant state = swipeRefreshState, 100*fa44fe6aSInna Palant onRefresh = { /* todo */ }, 101*fa44fe6aSInna Palant) { 102*fa44fe6aSInna Palant LazyColumn { 103*fa44fe6aSInna Palant items(30) { index -> 104*fa44fe6aSInna Palant // TODO: list items 105*fa44fe6aSInna Palant } 106*fa44fe6aSInna Palant } 107*fa44fe6aSInna Palant} 108*fa44fe6aSInna Palant``` 109*fa44fe6aSInna Palant 110*fa44fe6aSInna Palant## Indicator 111*fa44fe6aSInna Palant 112*fa44fe6aSInna PalantThe 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*fa44fe6aSInna Palant 114*fa44fe6aSInna Palant### Customizing default indicator 115*fa44fe6aSInna Palant 116*fa44fe6aSInna PalantTo customize the default indicator, we can provide our own `indicator` content block, to call [`SwipeRefreshIndicator()`][api_swiperefreshindicator] with customized parameters: 117*fa44fe6aSInna Palant 118*fa44fe6aSInna Palant=== "Sample" 119*fa44fe6aSInna Palant 120*fa44fe6aSInna Palant ``` kotlin 121*fa44fe6aSInna Palant SwipeRefresh( 122*fa44fe6aSInna Palant state = /* ... */, 123*fa44fe6aSInna Palant onRefresh = /* ... */, 124*fa44fe6aSInna Palant indicator = { state, trigger -> 125*fa44fe6aSInna Palant SwipeRefreshIndicator( 126*fa44fe6aSInna Palant // Pass the SwipeRefreshState + trigger through 127*fa44fe6aSInna Palant state = state, 128*fa44fe6aSInna Palant refreshTriggerDistance = trigger, 129*fa44fe6aSInna Palant // Enable the scale animation 130*fa44fe6aSInna Palant scale = true, 131*fa44fe6aSInna Palant // Change the color and shape 132*fa44fe6aSInna Palant backgroundColor = MaterialTheme.colors.primary, 133*fa44fe6aSInna Palant shape = MaterialTheme.shapes.small, 134*fa44fe6aSInna Palant ) 135*fa44fe6aSInna Palant } 136*fa44fe6aSInna Palant ) 137*fa44fe6aSInna Palant ``` 138*fa44fe6aSInna Palant 139*fa44fe6aSInna Palant=== "Demo video" 140*fa44fe6aSInna Palant 141*fa44fe6aSInna Palant <figure> 142*fa44fe6aSInna Palant <video width="480" controls loop> 143*fa44fe6aSInna Palant <source src="tweaked.mp4" type="video/mp4"> 144*fa44fe6aSInna Palant Your browser does not support the video tag. 145*fa44fe6aSInna Palant </video> 146*fa44fe6aSInna Palant <figcaption>Tweaked indicator demo</figcaption> 147*fa44fe6aSInna Palant </figure> 148*fa44fe6aSInna Palant 149*fa44fe6aSInna Palant### Custom indicator 150*fa44fe6aSInna Palant 151*fa44fe6aSInna PalantAs 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*fa44fe6aSInna Palant 153*fa44fe6aSInna PalantAn example of a custom indicator is provided [here][sample_customindicator]. 154*fa44fe6aSInna Palant 155*fa44fe6aSInna Palant## Download 156*fa44fe6aSInna Palant 157*fa44fe6aSInna Palant[](https://search.maven.org/search?q=g:com.google.accompanist) 158*fa44fe6aSInna Palant 159*fa44fe6aSInna Palant```groovy 160*fa44fe6aSInna Palantrepositories { 161*fa44fe6aSInna Palant mavenCentral() 162*fa44fe6aSInna Palant} 163*fa44fe6aSInna Palant 164*fa44fe6aSInna Palantdependencies { 165*fa44fe6aSInna Palant implementation "com.google.accompanist:accompanist-swiperefresh:<version>" 166*fa44fe6aSInna Palant} 167*fa44fe6aSInna Palant``` 168*fa44fe6aSInna Palant 169*fa44fe6aSInna PalantSnapshots of the development version are available in [Sonatype's `snapshots` repository][snap]. These are updated on every commit. 170*fa44fe6aSInna Palant 171*fa44fe6aSInna Palant [compose]: https://developer.android.com/jetpack/compose 172*fa44fe6aSInna Palant [snap]: https://oss.sonatype.org/content/repositories/snapshots/com/google/accompanist/accompanist-swiperefresh/ 173*fa44fe6aSInna Palant [api_swiperefreshstate]: ../api/swiperefresh/com.google.accompanist.swiperefresh/-swipe-refresh-state/ 174*fa44fe6aSInna Palant [api_swiperefreshindicator]: ../api/swiperefresh/com.google.accompanist.swiperefresh/-swipe-refresh-indicator.html 175*fa44fe6aSInna Palant [api_swiperefresh]: ../api/swiperefresh/com.google.accompanist.swiperefresh/-swipe-refresh.html 176*fa44fe6aSInna Palant [api_rememberstate]: ../api/swiperefresh/com.google.accompanist.swiperefresh/remember-swipe-refresh-state.html 177*fa44fe6aSInna Palant [sample_customindicator]: https://github.com/google/accompanist/blob/main/sample/src/main/java/com/google/accompanist/sample/swiperefresh/SwipeRefreshCustomIndicatorSample.kt 178*fa44fe6aSInna Palant [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*fa44fe6aSInna Palant [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*fa44fe6aSInna Palant [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*fa44fe6aSInna Palant [verticalscroll]: https://developer.android.com/jetpack/compose/gestures#scroll-modifiers 182