Ely*_*lye 5 android android-jetpack-compose
AnimationAsState
我使用、Animatable
、 和创建相同的动画UpdateTransition
并尝试它们。
所有动画都使用向前或向后移动。
tween(
durationMillis = 3000,
easing = LinearOutSlowInEasing
)
Run Code Online (Sandbox Code Playgroud)
我们可以在下面看到它
如果动画执行到一半,并且我再次单击按钮,我会假设运行的动画速度保持不变并传递到后续动画。
这对于AnimateAsState
和 来说似乎是正确的Animatable
。然而,令我惊讶的是,他们的UpdateTransition
行为似乎并非如此。我猜它已经恢复到默认的动画持续时间(运行得非常快)。
我们可以看到如下。
我的问题是,是吗
UpdateTransition
如果后续动画中途取消,预计不会保留正在运行的动画规范?UpdateTransition
错误,需要向 Google 报告吗?上述动画的完整工作代码如下
import androidx.compose.animation.core.*
import androidx.compose.animation.core.Animatable
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
@Composable
fun Combination() {
var enabled by remember { mutableStateOf(false) }
val dbAnimateAsState: Dp by animateDpAsState(
targetValue = switch(enabled),
animationSpec = animationSpec()
)
val dbAnimatable = remember { Animatable(0.dp) }
val transition = updateTransition(enabled, label = "")
val dbTransition by transition.animateDp(
transitionSpec = { animationSpec() }, label = "") {
switch(it)
}
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("AnimateAsState")
animateBoxHorizontal(dbAnimateAsState)
Text("Animatable")
animateBoxHorizontal(dbAnimatable.value)
Text("UpdateTransition")
animateBoxHorizontal(dbTransition)
Button(onClick = { enabled = !enabled }) {
Text("Click Me")
}
}
LaunchedEffect(key1 = enabled) {
dbAnimatable.animateTo(
targetValue = switch(enabled),
animationSpec = animationSpec()
)
}
}
private fun animationSpec(): TweenSpec<Dp> =
tween(
durationMillis = 3000,
easing = LinearOutSlowInEasing
)
private fun switch(enabled: Boolean) = if (enabled) 268.dp else 0.dp
fun Animatable(initialValue: Dp) = Animatable(
initialValue,
DpToVector,
)
private val DpToVector: TwoWayConverter<Dp, AnimationVector1D> =
TwoWayConverter({ AnimationVector1D(it.value) }, { it.value.dp })
@Composable
private fun animateBoxHorizontal(dbAnimateAsState: Dp) {
Box(
modifier = Modifier
.height(32.dp)
.width(300.dp)
.background(Color.Yellow)
) {
Box(
modifier = Modifier
.offset(dbAnimateAsState, 0.dp)
.size(32.dp)
.background(Color.Red)
)
}
Spacer(modifier = Modifier.height(16.dp))
}
Run Code Online (Sandbox Code Playgroud)
注意:更新信息
如果我从tweenSpec
改为springSpec
ie
tween(
durationMillis = 3000,
easing = LinearOutSlowInEasing
)
Run Code Online (Sandbox Code Playgroud)
到
spring(stiffness =20f, dampingRatio = 0.25f)
Run Code Online (Sandbox Code Playgroud)
然后updateTransition
像往常一样工作,当我们用新的动画中断时,弹簧速度和动画将被保留并连续。
updateTransition
仍然保持速度 - 如果你可以放慢速度,它可能会更明显。当中断时它会切换到 a spring
,而animateAsState
并Animatable
使用AnimationSpec
您提供的 。该回退弹簧可能有点太硬,因此它被认为是一个非常快的变化。
此设计的目的是允许Transition
在使用不同类型的 s 时适应中断AnimationSpec
。例如,从状态 A 到状态 B,您可能会使用keyFrames
,从状态 B 到状态 C 或可能会使用snap()
(因为状态 B 和 C 中的值相同)。因此,当您中断从 A -> B 的动画并以 C 作为新目的地时, 和keyframes
都会snap
看起来非常奇怪。这就是为什么我们会回退到spring
aTransition
被中断时。
请注意,如果您已经在 中使用 aspring
作为动画Transition
,则该 spring 将用于处理该动画中的中断,因为它与您的动画更相关。这就是为什么当您为上面代码片段中的过渡提供低刚度弹簧时,您会看到动画的“路线校正”速度要慢得多。
我们确实计划支持中断处理的自定义,您可以在其中指定中断时要使用的 AnimationSpec。这是计划作为未来的工作。如果您对如何处理中断有任何具体要求,或者回退弹簧应该慢一点,请随时提出功能请求。:)