android 如何显示一个可组合的对话框至少2秒?

lb3vh1jj  于 2023-05-05  发布在  Android
关注(0)|答案(1)|浏览(169)

我是新进入喷气背包组成,我真的很想知道我如何可以显示一个组合对话框至少2秒钟。目前,它隐藏得非常快,甚至不会显示在屏幕上。我为一个本地逻辑显示它,因为它隐藏得太快了。
通过使用下面的代码,我可以显示对话框,并禁用触摸外或按下返回按钮。对话框仍然在视图层次结构的顶部可见,但它很快就会隐藏起来。

@Composable
fun LoadingBox(modifier: Modifier) {
    Dialog(
        onDismissRequest = {},
        properties = DialogProperties(dismissOnClickOutside = false)
    ) {
        Surface(
            elevation = 4.dp,
            shape = RoundedCornerShape(dimensionResource(R.dimen.stroke_size))
        ) {
            Column(
                modifier = modifier
                    .background(color = Dark_Gray)
                    .padding(
                    start = dimensionResource(R.dimen.view_padding_start),
                    end = dimensionResource(R.dimen.view_padding_start)
                )
                .height(140.dp)
                .fillMaxHeight(),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center
        ) {
            LoadingAnimation()
            Text(
                text = stringResource(id = R.string.loading_message),
                fontWeight = FontWeight.ExtraBold,
                fontSize = 15.sp,
                color = Gray,
                modifier = Modifier
                    .padding(top = 30.dp)
                    .clipToBounds()
                    .testTag(Constants.TestTag.LOADER)
                    )
            }
        }
    }
}

使用下面的Singleton类的函数使对话框可见和隐藏。

/*
* Loading Dialog Functionality
*/
val loadingStateIndicator = MutableLiveData<LoadingState>()
fun onLoadingStateChanged(state: LoadingState) {
    when (state) {
        LoadingState.LOADING -> {
            _uiState.value = _uiState.value.copy(
                loading = true
            )
        }
        LoadingState.LOADED -> {
            _uiState.value = _uiState.value.copy(
                loading = false
            )
        }
    }
}

在这种情况下,Timer.schedule的使用是否是良好的实践?

dvtswwa3

dvtswwa31#

这就是我在评论中提出的策略。我认为如果你要做这样的事情,延迟应该在UI端处理,而不是在ViewModel中,因为延迟是UI细节,而不是模型状态的一部分。
在这里,它保持对话框打开至少两秒,但如果加载时间超过两秒,则在加载完成后立即关闭对话框。
这比我最初想象的要棘手。也许有一个更干净的方式我还没有想到。我还没测试过这个

// In some composable:
val loadingState by viewModel.loadingStateIndicator.observeAsState(LoadingState.LOADING)
val lastDialogOpenTime = remember(loadingState) { 
    if(loadingState == LoadingState.LOADING) System.currentTimeMillis() else 0L
}
val now = System.currentTimeMillis()
var shouldShowDialog by remember(loadingState) { 
    mutableStateOf(loadingState == LoadingState.LOADING || now > lastDialogOpenTime + 2000L)
}
LaunchedEffect(loadingState) {
    if(LoadingState == LoadingState.LOADED && shouldShowDialog) {
        delay(lastDialogOpenTime + 2000L - now) 
        shouldShowDialog = false
    }
}

if (shouldShowDialog) {
    LoadingBox()
}

或者这可以更简单地使用流来完成。您可以创建具有滞后状态更改的Flow。这个我也没试过

val laggedLoadingStateIndicator by remember { 
    viewModel.loadingStateIndicator.asFlow()
        .buffer() // I'm not sure if this is necessary
        .transform {
            emit(it)
            if (it == LoadingState.LOADING) {
                delay(2000)
            }
        }
        .collectAsState(LoadingState.LOADED)
}

if (laggedLoadingStateIndicator == LoadingState.LOADING) {
    LoadingBox()
}

相关问题