如何在 Jetpack Compose 中现有的 LazyColumn 之上添加 CircularProgressIndicator?

How to add a CircularProgressIndicator on top of existing LazyColumn in Jetpack Compose?

我有以下屏幕:

fun ItemsScreen(
    viewModel: ItemsViewModel = hiltViewModel()
) {
    val showProgressBarState = remember { mutableStateOf(false) }
    if (showProgressBarState.value) { ShowProgressBar() }

    when(val resource = viewModel.state.value) {
        is Loading -> ShowProgressBar() //Works perfectly
        is Success -> LazyColumn {
            items(
                items = resource.data
            ) { item ->
                ItemCard(
                    item = item
                )
            }
            when(val r = viewModel.s.value) {
                is Loading -> showProgressBarState.value = true
                is Success -> showProgressBarState.value = false
                is Failure -> Log.d(TAG, "Failure")
            }
        }
        is Failure -> Text(
            text = r.message,
            modifier = Modifier.padding(16.dp)
        )
    }
}

@Composable
fun ShowProgressBar() {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        CircularProgressIndicator()
    }
}

第二个“when”表示删除状态。我想当一个项目被删除时启动进度条。它开始但在 LazyColumn 后面。怎么加在前面?

这是我在 activity class:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        Scaffold(
            //
        ) {
            ItemsScreen()
        }
    }
}

将所有内容打包到 Box 中,并将进度条放在内容顶部。

Box(){
when(val resource = viewModel.state.value) {

    is Success -> LazyColumn {
    }
    is Loading -> ShowProgressBar() //move to top layer 
}
}

您正在更新视图生成器中的状态值。它在这种情况下会起作用,但通常这是一种不好的做法,可能会导致冗余重组,从而可能会减慢您的应用程序。我说的是这部分:

when(val r = viewModel.s.value) {
    is Loading -> showProgressBarState.value = true
    is Success -> showProgressBarState.value = false
    is Failure -> Log.d(TAG, "Failure")
}

您应该使用 side effects 更改状态。在这里您可以使用 LaunchedEffect,因此仅当指定的键自上次重组后更改时才会调用内容。:

LaunchedEffect(viewModel.s.value) {
    when (val r = viewModel.s.value) {
        is Loading -> showProgressBarState.value = true
        is Success -> showProgressBarState.value = false
        is Failure -> Log.d(TAG, "Failure")
    }
}

但实际上那是未来的题外话,在这种情况下你根本不需要 showProgressBarState

当您使用 Box 时,项目会在屏幕上显示在彼此之上。因为你需要在LazyColumn上面显示进度条,你需要用一个Box包裹它并且在LazyColumn.

之后放置ShowProgressBar

您也可以指定 contentAlignment = Alignment.Center 而不是用 Column 包装 CircularProgressIndicator:

is Resource.Success -> {
    Box(contentAlignment = Alignment.Center) {
        LazyColumn {
            items(
                items = resource.data
            ) { item ->
                ItemCard(
                    item = item
                )
            }
        }
        when (val r = viewModel.s.value) {
            is Resource.Loading -> CircularProgressIndicator()
            is Resource.Success -> Unit
            is Resource.Failure -> Log.d(TAG, "Failure")
        }
    }
}