Search code examples
androidandroid-jetpack-composematerial3

Material3 PullToRefreshContainer not working


  fun ProductsListScreen() {
       
    
        val lazyListState: LazyGridState = rememberLazyGridState()
        var isRefreshing by remember {
            mutableStateOf(false)
        }
        val pullToRefreshState = rememberPullToRefreshState(enabled = { isRefreshing })
        val scope = rememberCoroutineScope()
    
        Scaffold(modifier = Modifier.fillMaxSize(), topBar = {
            ///topAppBar
    
        }) { paddingValues ->
    
            Box(
                Modifier
                    .verticalScroll(rememberScrollState())
                    .nestedScroll(pullToRefreshState.nestedScrollConnection)
                    .fillMaxSize()
                    .padding(paddingValues)
            ) {
    
               
                    LazyVerticalGrid(
                        state = lazyListState,
                        modifier = Modifier
                            .fillMaxSize()
                            .padding(10.dp)
                            .padding(bottom = paddingValues.calculateBottomPadding()),
                        columns = GridCells.Fixed(2),
                        contentPadding = PaddingValues(5.dp)
                    ) {
                       /// Items 
                    }
                
    
                if (pullToRefreshState.isRefreshing) {
                    LaunchedEffect(true) {
                        scope.launch {
                            isRefreshing = true
                            productViewModel.loadProducts(forceRefresh = true)
                            isRefreshing = false
                        }
                    }
                }
                LaunchedEffect(isRefreshing) {
                    if (isRefreshing) {
                        pullToRefreshState.startRefresh()
                    } else {
                        pullToRefreshState.endRefresh()
                    }
                }
    
                PullToRefreshContainer(
                    state = pullToRefreshState,
                    modifier = Modifier
                        .align(Alignment.TopCenter),
                )
    
            }
    
        }
    
    
    }

I'm using composeBom version = "2024.04.01"

androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }

I can see PullRefreshIndicator on top but it not pulling. I tried to use pullToRefreshState with LazyGrid and Box but no results. I tried to show an indicator from MainScreen by Unit function on ProductsScreen but also no result.


Solution

  • The PullToRefreshContainer Composable has been replaced with PullToRefreshBox starting from material3:1.3.0. It was done in this commit and this file.

    Your Compose BOM is deprecated and still using material3:1.2.1 internally. Please update your Compose BOM to the latest version, which as of 11/2024 is

    composeBom = "2024.11.00"
    

    Then, follow the sample in the documentation. The PullToRefreshBox must be the parent Composable of the scrolling content. Also, it will show a default indicator by itself:

    @OptIn(ExperimentalMaterial3Api::class)
    @Composable
    fun ProductsListScreen() {
    
        val lazyGridState = rememberLazyGridState()
        var isRefreshing by remember {
            mutableStateOf(false)
        }
        val scope = rememberCoroutineScope()
    
        Scaffold(
            modifier = Modifier.fillMaxSize(),
            topBar = {
                //...
            }
        ) { paddingValues ->
    
            PullToRefreshBox(
                isRefreshing = isRefreshing,
                onRefresh = {
                    scope.launch {
                        isRefreshing = true
                        productViewModel.loadProducts(forceRefresh = true)
                        isRefreshing = false
                    }
                },
                modifier = Modifier
                    .fillMaxSize()
                    .padding(paddingValues)
            ) {
    
                LazyVerticalGrid(
                    state = lazyGridState,
                    modifier = Modifier
                        .fillMaxSize()
                        .padding(10.dp)
                        .padding(bottom = paddingValues.calculateBottomPadding()),
                    columns = GridCells.Fixed(2),
                    contentPadding = PaddingValues(5.dp)
                ) {
                    /// Items
                }
            }
        }
    }
    

    The PullToRefreshBox offers its own onRefresh callback, so you don't need to manually observe any PullToRefreshState.