我一直在努力让
animateItemPlacement()
在我的应用程序中正常工作,并认为它完全被破坏了,直到我发现其他人的示例似乎有效。
我终于弄清楚我的应用程序与其他示例有何不同:
在我正在开发的应用程序中,洗牌从未发生过,因此我花了一段时间才发现洗牌确实有效,而基本的添加和删除项目却不起作用。
独立的示例应用程序:
(抱歉,它只是桌面自动取款机,那是因为它使用 UUID 来生成 ID,而我还没有一个好的跨平台解决方案。我希望 Kotlin 将 UUID 添加到核心库中......你可能可以对它进行一个小调整,让它也可以在 Android 上运行,但我认为桌面是获得示例运行的最简单的平台。)
import androidx.compose.animation.core.EaseInOutCubic
import androidx.compose.animation.core.tween
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.darkColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.singleWindowApplication
import kotlinx.coroutines.delay
import java.util.UUID
fun main() = singleWindowApplication {
MaterialTheme(colorScheme = darkColorScheme()) {
Surface(modifier = Modifier.fillMaxSize()) {
ItemPlacementAnimationMockup()
}
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ItemPlacementAnimationMockup() {
val history = remember { mutableStateListOf<HistoryItem>() }
// Some simulated activity
LaunchedEffect(Unit) {
repeat(4) {
history.add(HistoryItem())
}
while (true) {
val newItem = HistoryItem()
delay(timeMillis = 1000)
history.add(newItem)
delay(timeMillis = 1000)
history.remove(newItem)
delay(timeMillis = 1000)
history.shuffle()
}
}
LazyColumn(
modifier = Modifier
.padding(16.dp)
// Uncomment the enxt line to align at the bottom instead
// .wrapContentHeight(Alignment.Bottom)
) {
items(history, key = { it }) {
Text("Item $it", Modifier.animateItemPlacement(animationSpec = tween(
durationMillis = 800,
easing = EaseInOutCubic,
)))
}
}
}
private data class HistoryItem(
val id: UUID = UUID.randomUUID(),
)
有没有办法让
animateItemPlacement()
适用于所有三种场景?
我知道我可以使用
animateContentSize()
来模拟动画添加和删除,但这实际上只是模拟,不适用于将一项添加到列表并同时删除其他项的情况。在这种情况下,内容大小不会改变,因此根本不会发生动画。
另一个可以尝试的选项是
animateItem
修改器,它将为项目的插入、删除和重新排序设置动画。
您可以按如下方式使用:
LazyColumn {
items(
items,
key = { it } // key is required for correct animations
) { item ->
Text(
modifier = Modifier.animateItem(), // apply Modifier
text = item.text
)
}
}