【发布时间】:2021-10-11 04:38:05
【问题描述】:
我想为两个状态之间的几个 Composable 设置动画,基本上从 Row 更改为 Column。在视图系统中,我会将这些放在ConstraintLayout 中,然后根据我要使用的布局更新约束——在 Jetpack Compose 上执行此操作的等效方法是什么?我也可以定义一个ConstraintLayout,但我对不依赖于它的解决方案感兴趣。
这是我尝试过的,但它不会为视图位置设置动画,它只是将一个淡出并淡入另一个。我知道每个状态的 2 个可组合项之间必须存在某种联系,以便它们可以动画化,但我不知道如何实现。
enum class ContentState {
One,
Two,
}
@ExperimentalAnimationApi
@Composable
fun ContentAnimator(
modifier: Modifier = Modifier,
state: ContentState = ContentState.One,
) {
Box(
modifier = modifier,
contentAlignment = Alignment.Center,
) {
AnimatedContent(
targetState = state,
) { targetState ->
when (targetState) {
ContentState.One -> OneLayout()
ContentState.Two -> TwoLayout()
}
}
}
}
@Composable
fun OneLayout() {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
Box(
modifier = Modifier
.size(width = 48.dp, height = 48.dp)
.background(Color.Red),
)
Spacer(modifier = Modifier.width(16.dp))
Text(
text = "Sample text",
style = MaterialTheme.typography.h3,
)
}
}
@Composable
fun TwoLayout() {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Box(
modifier = Modifier
.size(width = 48.dp, height = 48.dp)
.background(Color.Red)
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "Sample text",
style = MaterialTheme.typography.h3,
)
}
}
我想在下面显示的这两种状态之间来回切换。我认为另一种选择是使用Layout 和animatable 对象,然后根据animatable 手动计算这两个对象的位置,但这似乎是一个非常低级的解决方案。
【问题讨论】:
-
要为对象设置动画,它必须是 Compose 树中完全相同的对象,并且在您的代码中,您可以为不同的布局创建不同的视图。 `ConstraintLayout' 之所以有效,是因为通过更改约束您正在移动相同的视图,而不是创建新视图。请参阅Demystify SwiftUI:它讨论了一个不同的声明式 UI 框架,但在 Compose 中,出于相同的原因,它的工作方式完全相同。
-
谢谢,我明白了,但是除了使用 ConstraintLayout 或手动移动布局中的视图之外,还有其他方法吗?这就是我要问的。
-
@Philip,我想我不同意这一点。 Here 是一个使用两个不同视图的示例,但如果您定义自定义 transitionSpec,它就可以正常工作。只需在他们解释
SizeTransform(可组合?)的部分向下滚动一下即可 -
哦,这是可组合而不是视图
-
AnimatedContent也是我想到的第一个地方,但我认为在不必要的时候使用这些 API 是没有必要的。为什么不能只使用 animateDpAsState 为自定义 Composable 中的 Offset 设置动画?AnimatedContent不支持单独为子可组合项设置动画,因此使其工作有点复杂。试试另一种方法,或者如果您需要一些样品或其他东西,请告诉我们
标签: android android-jetpack-compose