JBrown
JBrown

Reputation: 11

How to use SwipeRefresh with Jetpack Compose LazyColumn and reverseLayout

I am trying to create a chat feature in app. We would like the layout to be reversed in the column for easier scrolling. However, we cannot get the SwipeRefresh to work in this configuration if the list is large enough to scroll. Preferably, we would like to be able to swipe up from the bottom to refresh, but even with trying to use the regular SwipeRefresh from the top, it does not work unless we remove the 'reverseLayout = true'. Has anyone been able to use the reverse layout with the SwipeRefresh or the PullRefresh?

@Composable
fun CRFilesPage(
    uiState: StateFlow<ViewModel.UiState>,
    refreshList: () -> Unit
) {

    val state = uiState.collectAsState()
    val lazyListState: LazyListState = rememberLazyListState()
    val swipeRefreshState = rememberSwipeRefreshState(isRefreshing = state.value.isSending)

    SwipeRefresh(
        state = swipeRefreshState,
        onRefresh = { refreshList.invoke() },
        modifier = Modifier

    ) {

        LazyColumn(
            state = lazyListState,
            reverseLayout = true
        ) {

            items(items = state.value.comments, key = { it.id }) {
                Text(text = it.comment)
            }
        }
    }
}


Upvotes: 1

Views: 1207

Answers (1)

David Sucharda
David Sucharda

Reputation: 51

So I do not see the option in compose material just yet. I see some comments in the code to allow custom PullRefreshStates but they are not in just yet. So I took the current code from compose material 1.4.0-rc01 and modified it to support reverseLayout option.

I realized that I put a lot of code here so I moved all of it to: https://gist.github.com/Del-S/f0d4ee78eba893ecde7b15393dfff4c1.

It contains ReversiblePullRefresh with all the functionality required. It supports default layout state and reverse layout state. And it also contains a refresh indicator which should work properly.


USAGE: It is pretty much the same as with the default PullRefresh wich addition of reverseLayout property.

@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun ReversedList(
    messages: List<String>,
    modifier: Modifier = Modifier
) {
    val reverseLayout = true
    val refreshScope = rememberCoroutineScope()
    var refreshing by remember { mutableStateOf(false) }

    fun triggerPagingRefresh() = refreshScope.launch {
        refreshing = true
        // Here should be your refresh logic (or it can be passed as lambda into Composable function).
        delay(2_000L)
        refreshing = false
    }

    val state = rememberReversiblePullRefreshState(
        refreshing = refreshing,
        onRefresh = ::triggerPagingRefresh,
        reverseLayout = reverseLayout
    )

    Box(modifier.reversiblePullRefresh(state = state, reverseLayout = reverseLayout)) {
        LazyColumn(reverseLayout = reverseLayout) {
            items(messages) { item ->
                Text(text = item)
            }
        }

        ReversiblePullRefreshIndicator(
            refreshing = refreshing,
            state = state,
            modifier = Modifier.align(Alignment.BottomCenter.takeIf { reverseLayout } ?: Alignment.TopCenter),
            reverseLayout = reverseLayout
        )
    }
}

Yep and that is it. It seems like a lot but it is just a little modification of already existing code. In my code it works like this:

Pull refresh start Pull refresh continue Pull refresh in progress
Pull refresh start Pull refresh continue Pull refresh in progress

Upvotes: 2

Related Questions