撰写自定义布局中的 animateFloatAsState 未对所有可组合项进行动画处理
animateFloatAsState in compose custom layout not animating all composables
我有一个自定义布局,它是一个类似日历的屏幕,用户可以将其作为一个整体拖动。在屏幕上可见的时间范围内对用户可见的事件使用 placeables/measurable.
绘制
我有一个功能,当用户将事件部分拖出屏幕时,内容中的标题会粘在事件的顶部,直到它被完全拖出屏幕。
发生这种情况时,我会在顶部添加一个小图像以指示事件在其上方继续进行
例如
"Event Name"
变成
^
"Event Name"
我想为“事件名称”文本设置动画,使其随着 ^ 出现或消失而向下移动,而不是当我 insert/remove 重新组合 ^ 时它简单地向下跳。
看起来这就是我需要的正确动画文本
@Composable
fun TestItem(event: Event) {
val offset: Float by animateFloatAsState(if (event.isPartiallyOffScreen)) 100f else 0f)
Box(Modifier.background(color=event.color)) {
Text(
text = event.name,
modifier = Modifier.graphicsLayer(
translationY = offset
)
)
}
}
当内容在 on/off 屏幕之间切换时,这确实使文本平滑地向下和向上动画,但问题是,我在屏幕上有几十个这样的东西,它只适用于第一个项目在一列中,直到出现间隙。
例
事件 811 将在文本离开屏幕时将其动画化,当事件 195 开始离开屏幕时,它会在它发生的那一刻从 0 跳到 100,然后事件 757 将工作并正确地为文本设置动画,尽管在之后做个动图,757也有点卡顿了。
这几乎就像是因为事件 811 可组合项在完全离开屏幕后就不再存在,它认为事件 195 是事件 811,因为它占据了可放置顺序中的那个位置,现在它开始离开屏幕并重复使用之前的事件价值观?当它达到 757 时,它已经消失了很多次,它有点像预期的那样工作?
更新:我已经确认,如果我停止从列表中删除项目(如果它们不在屏幕上),它将按预期在所有项目上工作,但性能下降和卡顿是相当大的,因为有超过 80-正在绘制 100 个项目,大部分都在屏幕外,所以这不是一个真正的选择。
我也尝试过使用 LaunchedEffects 以及来自事件的唯一键,但它也不起作用?
这是可组合项中唯一有状态的东西,其他一切都只是从构造函数内容中设置的值
我对如何解决这个问题感到困惑。
在确认如果我不移除屏幕外可组合项我的屏幕将正常工作后,它证实了我的怀疑,即由于所有项目都相同,重新组合变得混乱。
我以为在动画上使用键可以解决问题,但事实并非如此。我需要的是这个答案中描述的可组合项的键
所以对我来说,我需要将自定义布局中的每个事件包装在 key
可组合项
中
Layout(
modifier = modifier.fillMaxHeight()
content = {
eventList.forEach { event ->
key(event) {
TestItem(displayPerformance, adjustedStart)
}
}
},
) { measureables, constraints ->
我有一个自定义布局,它是一个类似日历的屏幕,用户可以将其作为一个整体拖动。在屏幕上可见的时间范围内对用户可见的事件使用 placeables/measurable.
绘制我有一个功能,当用户将事件部分拖出屏幕时,内容中的标题会粘在事件的顶部,直到它被完全拖出屏幕。
发生这种情况时,我会在顶部添加一个小图像以指示事件在其上方继续进行
例如
"Event Name"
变成
^
"Event Name"
我想为“事件名称”文本设置动画,使其随着 ^ 出现或消失而向下移动,而不是当我 insert/remove 重新组合 ^ 时它简单地向下跳。
看起来这就是我需要的正确动画文本
@Composable
fun TestItem(event: Event) {
val offset: Float by animateFloatAsState(if (event.isPartiallyOffScreen)) 100f else 0f)
Box(Modifier.background(color=event.color)) {
Text(
text = event.name,
modifier = Modifier.graphicsLayer(
translationY = offset
)
)
}
}
当内容在 on/off 屏幕之间切换时,这确实使文本平滑地向下和向上动画,但问题是,我在屏幕上有几十个这样的东西,它只适用于第一个项目在一列中,直到出现间隙。
例
事件 811 将在文本离开屏幕时将其动画化,当事件 195 开始离开屏幕时,它会在它发生的那一刻从 0 跳到 100,然后事件 757 将工作并正确地为文本设置动画,尽管在之后做个动图,757也有点卡顿了。
这几乎就像是因为事件 811 可组合项在完全离开屏幕后就不再存在,它认为事件 195 是事件 811,因为它占据了可放置顺序中的那个位置,现在它开始离开屏幕并重复使用之前的事件价值观?当它达到 757 时,它已经消失了很多次,它有点像预期的那样工作?
更新:我已经确认,如果我停止从列表中删除项目(如果它们不在屏幕上),它将按预期在所有项目上工作,但性能下降和卡顿是相当大的,因为有超过 80-正在绘制 100 个项目,大部分都在屏幕外,所以这不是一个真正的选择。
我也尝试过使用 LaunchedEffects 以及来自事件的唯一键,但它也不起作用?
这是可组合项中唯一有状态的东西,其他一切都只是从构造函数内容中设置的值
我对如何解决这个问题感到困惑。
在确认如果我不移除屏幕外可组合项我的屏幕将正常工作后,它证实了我的怀疑,即由于所有项目都相同,重新组合变得混乱。
我以为在动画上使用键可以解决问题,但事实并非如此。我需要的是这个答案中描述的可组合项的键
所以对我来说,我需要将自定义布局中的每个事件包装在 key
可组合项
Layout(
modifier = modifier.fillMaxHeight()
content = {
eventList.forEach { event ->
key(event) {
TestItem(displayPerformance, adjustedStart)
}
}
},
) { measureables, constraints ->