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

31
我试图在一列中显示和隐藏进度指示器 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大小?

谢谢


10
你可以尝试使用 alpha 值为 0 - CommonsWare
@CommonsWare 很完美,谢谢。 - Ehsan msz
5个回答

23

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

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

我尝试了这个:如果工作正常,它将是不可见的,但小部件会有空白空间。 - Bolt UIX
1
@HariShankarS 这是“invisible”预期的行为。如果你想要它被移除,应该使用“gone”。 - m0skit0
11
请注意,任何按钮或类似的元素即使不可见仍然可以被点击。 - m.reiter
@m.reiter 谢谢提及。 - Akbolat SSS
@m.reiter 所以对于一个按钮,你可以使用 onClick = { if (condition) onClick() } 来解决这个问题。 - undefined
1
@MarioHuizinga.clickable(enabled = condition){ onClick() }` 可以随时使用。 - undefined

5

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

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) 
            }
        }
    }
}

这似乎在与Icon()一起使用时无法正常工作。由于某种原因,它没有被正确地重新组合。 - undefined

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

它还可以用于观察动画状态。

4
这不会使内容变得看不见,相反它会移除它(类似于 GONE)。 - ubuntudroid

2
您的解决方案是正确的,但您还可以将进度指示器包装在期望大小的框中。
Box(modifier = Modifier.height(40.dp) {
    if (condition) {
        CircularProgressIndicator()
    }
}

谢谢你的回答。这个解决方案很好,但我必须手动设置 Modifier.height() - Ehsan msz
同时,重要的是要说,这样做将始终重新创建可组合。然后,如果其中有一些副作用(例如),所有这些效果都将被重新创建。要小心。 - Lucas Sousa

0

使用:

Spacer(modifier = Modifier.height(24.dp))

请阅读如何撰写好的回答。虽然该代码块可能会回答OP的问题,但如果您解释一下这段代码与问题中的代码有何不同,您做了哪些更改,为什么要更改以及为什么可以解决问题而不引入其他问题,那么这个答案将会更加有用。 - Saeed Zhiany

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接