There is something similar like swiperefreshlayout to pull to refresh in the LazyColumn jetpack compose
Asked Answered
S

3

25

There is something similar like swiperefreshlayout to pull to refresh in the jetpack compose

Shena answered 22/4, 2021 at 0:2 Comment(2)
Looks like a duplicate of https://mcmap.net/q/537826/-overscroll-handling-in-jetpack-compose/4136777Hellish
@DuncanLukkenaer, that solution is outdated now.Degrade
G
8

The Google's Accompanist is now deprecated. Official support is now available in Compose Material from versin 1.3.0 use following code:

The lines I marked with 1, 2, 3 does the job:

val ptrState= 
   rememberPullRefreshState(viewState.isRefreshing, {viewModel.pullToRefresh()}) // 1

Box(modifier = Modifier
    .fillMaxSize()
    .pullRefresh(ptrState)) { // 2
    LazyColumn(state = rememberLazyListState()) {
        items(
            items = viewState.YOUR_LIST_ITEMS,
            key = { item -> item.id },
            itemContent = {
                YourItemCompose(it)
            })
    }
    PullRefreshIndicator
          (viewState.isRefreshing, ptrState, Modifier.align(Alignment.TopCenter)) // 3
}

viewState.isRefreshing is a boolean holding your refresh state and viewModel.pullToRefresh() is the method to do the actual work for refreshing the data (e.g. calling the API again)

in case you don't know the dependency:

    implementation 'androidx.compose.material:material:1.4.0-alpha02' 
Gefen answered 17/11, 2022 at 22:57 Comment(1)
While it works, viewState.isRefreshing is not changing and it's value is not used.Degrade
M
47

Edit: Google Accompanist's swipe refresh is deprecated with official pull refresh support in androidx.compose.material.pullrefresh

Sample usage:

val viewModel: MyViewModel = viewModel()
val refreshing by viewModel.isRefreshing

val pullRefreshState = rememberPullRefreshState(refreshing, { viewModel.refresh() })

Box(Modifier.pullRefresh(pullRefreshState)) {
    LazyColumn(Modifier.fillMaxSize()) {
        ...
    }

    PullRefreshIndicator(refreshing, pullRefreshState, Modifier.align(Alignment.TopCenter))
}

Original Answer:

You can use Google's Accompanist library for implementing swipe-to-refresh.

Sample usage:

val viewModel: MyViewModel = viewModel()
val isRefreshing by viewModel.isRefreshing.collectAsState()

SwipeRefresh(
    state = rememberSwipeRefreshState(isRefreshing),
    onRefresh = { viewModel.refresh() },
) {
    LazyColumn {
        items(30) { index ->
            // TODO: list items
        }
    }
}

Documentation: https://google.github.io/accompanist/swiperefresh/

Mosenthal answered 22/4, 2021 at 5:2 Comment(1)
Swipe to refresh is deprecated in Accompanist and is now available in Compose Material: developer.android.com/reference/kotlin/androidx/compose/…Headforemost
F
26

Starting with M2 1.3.0-beta03 there is a new built-in Pull-To-Refresh component, with the pullRefresh modifier.

You can use something like:

val refreshScope = rememberCoroutineScope()
var refreshing by remember { mutableStateOf(false) }
var itemCount by remember { mutableStateOf(15) }

fun refresh() = refreshScope.launch {
    refreshing = true
    delay(1500)
    itemCount += 5
    refreshing = false
}

val state = rememberPullRefreshState(refreshing, ::refresh)

//pullRefresh modifier
Box(Modifier.pullRefresh(state)) {

    //vertically scrollable content
    LazyColumn(Modifier.fillMaxSize()) {
        if (!refreshing) {
            items(itemCount) {
                ListItem { Text(text = "Item ${itemCount - it}") }
            }
        }
    }

    //standard Pull-Refresh indicator. You can also use a custom indicator 
    PullRefreshIndicator(refreshing, state, Modifier.align(Alignment.TopCenter))
}

enter image description here

Note: currently, the content of the Composable with the pullRefresh modifier needs to be 'vertically scrollable' to be able to react to swipe gestures. Layouts such as LazyColumn are automatically vertically scrollable, in the other cases you can provide a verticalScroll modifier to that content.

Something like:

//pullRefresh modifier
Box( Modifier.pullRefresh(state) ) {

    //vertically scrollable content
    Column(Modifier.verticalScroll(rememberScrollState())) {
        // content
    }

    //PullRefreshIndicator
}
Fresnel answered 4/10, 2022 at 21:30 Comment(4)
Is there a built-in Pull-To-Refresh component for Material3?Maddie
@Maddie Not currentlyFresnel
why can i only use this with LazyColumn? it doesen't work with fullscreen box or colymn neitherBreger
@DaniilPozdnyakov I've updated the answer. You have to use a vertically scrollable content, not necessarily a LazyColumn to use the pullRefresh modifier.Fresnel
G
8

The Google's Accompanist is now deprecated. Official support is now available in Compose Material from versin 1.3.0 use following code:

The lines I marked with 1, 2, 3 does the job:

val ptrState= 
   rememberPullRefreshState(viewState.isRefreshing, {viewModel.pullToRefresh()}) // 1

Box(modifier = Modifier
    .fillMaxSize()
    .pullRefresh(ptrState)) { // 2
    LazyColumn(state = rememberLazyListState()) {
        items(
            items = viewState.YOUR_LIST_ITEMS,
            key = { item -> item.id },
            itemContent = {
                YourItemCompose(it)
            })
    }
    PullRefreshIndicator
          (viewState.isRefreshing, ptrState, Modifier.align(Alignment.TopCenter)) // 3
}

viewState.isRefreshing is a boolean holding your refresh state and viewModel.pullToRefresh() is the method to do the actual work for refreshing the data (e.g. calling the API again)

in case you don't know the dependency:

    implementation 'androidx.compose.material:material:1.4.0-alpha02' 
Gefen answered 17/11, 2022 at 22:57 Comment(1)
While it works, viewState.isRefreshing is not changing and it's value is not used.Degrade

© 2022 - 2024 — McMap. All rights reserved.