Home > Software design >  Jetpack Compose: How to center an item in LazyVerticalGrid?
Jetpack Compose: How to center an item in LazyVerticalGrid?

Time:06-28

I have a LazyVerticalGrid composable that shows my items. I want to show an error message with a button in the center of LazyVerticalGrid when an error has occured. Here is my error item and my LazyVerticalGrid:

ErrorItem

@Composable
fun ErrorItem(
    message: String,
    modifier: Modifier = Modifier,
    onRetryClick: () -> Unit,
) {
    Column(
        modifier = modifier
            .padding(dimensionResource(id = R.dimen.dimen_8)),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Text(
            text = message,
            maxLines = 1,
            style = MaterialTheme.typography.subtitle2,
            color = MaterialTheme.colors.error,
            modifier = Modifier.padding(vertical = dimensionResource(id = R.dimen.dimen_16))
        )
        Button(
            onClick = onRetryClick,
            shape = CircleShape,
            colors = ButtonDefaults.buttonColors(
                backgroundColor = MaterialTheme.colors.error,
                contentColor = MaterialTheme.colors.onError
            )
        ) {
            Text(text = stringResource(id = R.string.try_again))
        }
    }
}

@Composable
fun CompaniesScreen(
    modifier: Modifier = Modifier
) {
    val viewModel: CompaniesScreenViewModel = hiltViewModel()

    val companies: LazyPagingItems<Company> = viewModel.companies.collectAsLazyPagingItems()

    val isLoading = companies.loadState.refresh is LoadState.Loading

    val isError = companies.loadState.refresh is LoadState.Error

    val swipeRefreshState = rememberSwipeRefreshState(isRefreshing = isLoading)

    val listState = rememberLazyGridState()


    Scaffold(modifier = modifier, topBar = { LogoToolbar() }) { padding ->

        SwipeRefresh(indicator = { state, trigger ->
            SwipeRefreshIndicator(
                state = state,
                refreshTriggerDistance = trigger,
                scale = true,
                backgroundColor = MaterialTheme.colors.primary,
                contentColor = MaterialTheme.colors.onPrimary
            )
        }, state = swipeRefreshState, onRefresh = companies::refresh) {
            LazyVerticalGrid(
                state = listState,
                modifier = Modifier
                    .fillMaxSize()
                    .padding(
                        horizontal = dimensionResource(id = R.dimen.dimen_20),
                        vertical = dimensionResource(
                            id = R.dimen.dimen_24
                        )
                    ),
                columns = GridCells.Fixed(2),
                horizontalArrangement = Arrangement.spacedBy(dimensionResource(id = R.dimen.dimen_20)),
                verticalArrangement = Arrangement.spacedBy(
                    dimensionResource(
                        id = R.dimen.dimen_24
                    )
                )
            ) {
                if (!isLoading && !isError) {
                    items(companies.itemCount) { index ->
                        CompanyItem(companyName = companies[index]?.name!!)
                    }
                }
                companies.apply {
                    when {
                        loadState.refresh is LoadState.Loading -> {
                            items(16) {
                                CompanyItem(companyName = "", isLoading = true)
                            }
                        }
                        loadState.refresh is LoadState.Error -> {
                            val e = companies.loadState.refresh as LoadState.Error
                            item(span = {GridItemSpan(2)}) {
                                ErrorItem(
                                    modifier = Modifier.fillMaxSize(), // fillParentMaxSize() is not working
                                    message = e.error.localizedMessage
                                        ?: stringResource(id = R.string.something_went_wrong),
                                    onRetryClick = companies::retry
                                )
                            }
                        }
                    }
                }
            }
        }
    }
}

I have tried to use fillParentMaxSizewith my ErrorItem but it is not working. Here is the result :

enter image description here

CodePudding user response:

If you place your LazyVerticalGrid and ErrorItem inside a Box with contentAlignment = Alignment.Center ErrorItem will show center of your Box when isError is true

Box(
    modifier= Modifier.fillMaxSize(), 
    contentAlignment = Alignment.Center){
    LazyVerticalGrid(
       // Rest of the properties
    )

    if (isError){
        ErrorItem(""){

        }
    }
}
  • Related