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.
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
.