如何使小部件在 Jetpack Compose 中不可见?

问题描述 投票:0回答:6

我正在尝试在列中显示和隐藏

ProgressIndicator
。 问题是当我想隐藏
ProgressIndicator
时,其他小部件之间的空间也会被删除(如
View.GONE
),但我想保持小部件大小(如
View.INVISIBLE

示例:

@Composable
fun Main(isLoading: Boolean) {
    Column {
        Text(text = "Text")

        if (isLoading) {
            CircularProgressIndicator()
        }

        Button(onClick = { /*clicked*/ }, content = { Text(text = "Button") })    
    }
}

我找到了解决方案,但我不确定这是否是正确的方法。

if (isLoading) {
    CircularProgressIndicator()
} else {
    Spacer(modifier = Modifier.height(40.dp))
}

有没有其他方法可以让小部件像

View.INVISIBLE
一样不可见?

如何获取小部件尺寸来设置

Spacer
尺寸?

谢谢

android kotlin android-jetpack-compose
6个回答
30
投票

使用 Alpha Zero ,@commonsware 的评论中提到了这一点,因为您不需要知道空间大小的大小,这与需要特定大小的 Spacer() 可组合项不同,在某些情况下这可能很难要知道。

val commentsAlpha = if (condition) 1f else 0f
modifier = Modifier
            .alpha(commentsAlpha)

7
投票

您可以使用自定义布局修饰符,它定义要使其不可见的可组合项的空白区域。它还可以防止在不可见时接收任何触摸事件。

fun Modifier.visibility(visible: Boolean): Modifier {
    return layout { measurable, constraints ->
        val placeable = measurable.measure(constraints)

        layout(placeable.width, placeable.height) {
            if (visible) {
                // place this item in the original position
                placeable.placeRelative(0, 0) 
            }
        }
    }
}

4
投票

我正在使用以下方法:AnimatedVisibility https://developer.android.com/jetpack/compose/animation#animatedvisibility

 // Create a MutableTransitionState<Boolean> for the AnimatedVisibility.
                val state = remember {
                    MutableTransitionState(false).apply {
                        // Start the animation immediately.
                        targetState = true
                    }
                }
                Column {
                    AnimatedVisibility(visibleState = state) {
                        Text(text = "Hello, world!")
                    }

                    // Use the MutableTransitionState to know the current animation state
                    // of the AnimatedVisibility.
                    Text(
                        text = when {
                            state.isIdle && state.currentState -> "Visible"
                            !state.isIdle && state.currentState -> "Disappearing"
                            state.isIdle && !state.currentState -> "Invisible"
                            else -> "Appearing"
                        }
                    )
                }

enter image description here

对于观察动画状态也很有用。


2
投票

您的解决方案是正确的,但您也可以将进度指示器包装在预期大小的框中

Box(modifier = Modifier.height(40.dp) {
    if (condition) {
        CircularProgressIndicator()
    }
}

1
投票

用途:

if (isLoading) {
    CircularProgressIndicator(modifier = Modifier.height(24.dp))
} else {
    Spacer(modifier = Modifier.height(24.dp))
}

0
投票

我的实现存在一些极端情况,但如果您有一个简单的可组合项,那么它的工作原理和功能与您的使用方式非常相似

AnimateVisibility

@Composable
fun ColumnScope.AnimateInvisibility(
    visible: Boolean,
    enter: EnterTransition = fadeIn() + expandVertically(),
    exit: ExitTransition = fadeOut() + shrinkVertically(),
    label: String = "AnimatedInvisibility",
    modifier: Modifier = Modifier,
    content: @Composable (modifier: Modifier) -> Unit
) {
    Box(modifier) {
        [email protected](
            visible = visible,
            enter = enter,
            exit = exit,
            label = label
        ) {
            content(modifier = Modifier)
        }
        // Note: doesn't work well if you have clickable objects underneath
        content(modifier = Modifier.graphicsLayer { alpha = 0f })
    }
}

这是一种无需测量即可实施的方法

AnimateInvisibility(visible = isVisible) { modifier ->
    Text(
        text = "Hello World",
        modifier = modifier // it's important to use this modifier since we apply the 0f alpha on it
    )
}
© www.soinside.com 2019 - 2024. All rights reserved.