Search code examples
androidkotlinandroid-jetpack-composepull-to-refresh

Manually Pulling in PullToRefresh doesn't work (with replicable sample)


Im trying to implement the PullToRefresh Component from the material library, but even with a 1 to 1 replication of Google's own code, the swiping does not trigger anything. https://developer.android.com/reference/kotlin/androidx/compose/material/pullrefresh/package-summary.html

I've been able to reduce their code to a minimum replicable sample. Loader will show if you manually set it to true, but will not trigger on swiping.

The view does not expect any other content, as in, the loader should show regardless of what else is in the Box component.

import androidx.compose.foundation.layout.*
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun PullToRefreshComposableTEST() {

    var loading by remember {
        mutableStateOf(true)
    }

    val pullRefreshState = rememberPullRefreshState(
        refreshing = loading,
        onRefresh = {
            loading = true
        })

    Box(
        Modifier.fillMaxSize().pullRefresh(pullRefreshState)
    ) {
        PullRefreshIndicator(
            modifier = Modifier.align(Alignment.TopCenter),
            refreshing = loading,
            state = pullRefreshState
        )
    }
}

@Preview(showSystemUi = true)
@Composable
private fun Preview() {
    PullToRefreshComposableTEST()
}

Solution

  • Not sure what's not working but based on this

    Loader will show if you manually set it to true, but will not trigger on swiping.

    I'm assuming PullRefresh is not showing when you try to pull it down.

    Based on the docs,

    … The content needs to be 'vertically scrollable' for SwipeRefresh() to be able to react to swipe gestures. Layouts such as LazyColumn are automatically vertically scrollable, but others such as Column or LazyRow are not. In those instances, you can provide a Modifier.verticalScroll modifier…

    Just add a vertical scroll to your Box so you can pull it down

    Your modified code:

    @OptIn(ExperimentalMaterialApi::class)
    @Composable
    fun PullToRefreshComposableTEST() {
    
        var loading by remember {
            mutableStateOf(false)
        }
    
        val pullRefreshState = rememberPullRefreshState(
            refreshing = loading,
            onRefresh = {
                loading = !loading
            })
    
        Box(
            Modifier
                .fillMaxSize()
                .pullRefresh(pullRefreshState)
                .verticalScroll(rememberScrollState())
        ) {
            PullRefreshIndicator(
                modifier = Modifier.align(Alignment.TopCenter),
                refreshing = loading,
                state = pullRefreshState
            )
        }
    }
    

    enter image description here