[英]Jetpack Compose MutableTransitionState currentState holds wrong value
我使用AnimatedVisibility
來動畫從LazyColumn
刪除一個項目以及MutableTransitionState
來捕捉動畫結束以從LazyColumn
的列表中刪除這個項目。
我為此編寫了一個方便的擴展函數:
@ExperimentalTransitionApi
fun MutableTransitionState<Boolean>.transitionState(): TransitionState =
if (this.isIdle && this.currentState) TransitionState.Visible
else if (this.isIdle && !this.currentState) TransitionState.Invisible
else if (!this.isIdle && this.currentState) TransitionState.Disappearing
else TransitionState.Appearing
enum class TransitionState(private val whatever: Int) {
Visible(1),
Appearing(2),
Invisible(-1),
Disappearing(-2)
}
從某種意義上說,它返回正確的值(經過測試)是正確的,但currentState
似乎只是最初為false
,所以我無法捕捉到我唯一感興趣的事件 - Invisible
。
這是我的LazyColumn
:
val items by viewModel.itemsFlow.collectAsState()
LazyColumn(
verticalArrangement = Arrangement.spacedBy(10.dp),
contentPadding = PaddingValues(horizontal = 15.dp, vertical = 15.dp)
) {
items(items) { item ->
val animationState = remember {
MutableTransitionState(false) // The only time currentState is false!
}.apply { targetState = true }
AnimatedVisibility(
visibleState = animationState,
enter = slideInVertically() + fadeIn(),
exit = slideOutHorizontally(
targetOffsetX = { it*2 },
animationSpec = tween(
durationMillis = 700
)
)
) {
ItemCard(
item = item,
viewModel = viewModel,
animationState = animationState
)
}
}
}
我的ItemCard
有一個將animationState.tagetValue
更改為false
的Button
,並且狀態記錄在卡片中:
Card {
Log.v("ANIMATION", "View ${item.name} is now ${animationState.transitionState().name}")
Log.v("ANIMATION", "View ${item.name} has values: isIdle = ${animationState.isIdle}, currentState = ${animationState.currentState}")
/*...*/
Button(
/*...*/
onClick = {
animationState.targetState = false
}
) {/*...*/}
}
很不幸,我的日志是這樣的:
V/ANIMATION: View name is now Appearing
V/ANIMATION: View name has values: isIdle = false, currentState = false
V/ANIMATION: View name is now Appearing
V/ANIMATION: View name has values: isIdle = false, currentState = false
V/ANIMATION: View name is now Visible
V/ANIMATION: View name has values: isIdle = true, currentState = true
V/ANIMATION: View name is now Visible
V/ANIMATION: View name has values: isIdle = true, currentState = true
// After I click the button:
V/ANIMATION: View name is now Disappearing
V/ANIMATION: View name has values: isIdle = false, currentState = true
V/ANIMATION: View name is now Disappearing
V/ANIMATION: View name has values: isIdle = false, currentState = true
V/ANIMATION: View name is now Disappearing
V/ANIMATION: View name has values: isIdle = false, currentState = true
那么隱形狀態在哪里,即false
currentState
? 我做錯了什么嗎?
每次更改狀態時,都會觸發相關的視圖重組。 並且您在每次重新組合時使用.apply { targetState = true }
將animationState
設置為true
。
很可能您想在開始時顯示動畫,然后您需要使用LaunchedEffect
:它只會在視圖出現時調用一次。
val animationState = remember {
MutableTransitionState(false)
}
LaunchedEffect(Unit) {
animationState.targetState = true
}
閱讀更多關於Thinking in Compose 中的重組和狀態文檔中 Compose 中的state 的更多信息。
我在一個單獨的項目中測試了這種類型的動畫,並發現AnimatedVisibility
內容在animationState
發出其最終值之前已被處理,因此您不可能從您正在制作動畫的視圖內部捕獲它。
按照@Philip Dukhov 的建議,我的LazyColumn
項目現在是這樣的:
val animationState by remember {
mutableStateOf(MutableTransitionState(false))
}
LaunchedEffect(Unit) {
animationState.targetState = true
}
when(animationState.transitionState()) {
TransitionState.Invisible -> viewModel.deleteInvisibleItems()
else -> {}
}
Log.v("ANIMATION", "View ${item.name} is now ${animationState.transitionState().name}")
這可以完美地捕獲發出的值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.