本文介绍了AnimatedVisibility&SwipeToDismisse输入动画不会触发-Jetpack Compose的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,我一直在尝试在我的应用程序中实现滑动删除功能。每当我滑动列表中的一项时,我都能看到后面的红色背景,一切都运行得很好。同时,当我删除一个项目时,滑动动画也被成功触发。(尽管我不确定使用延迟是不是一个好主意?我想不出任何其他方法来做这件事)。但是向数据库/列表添加项目时输入动画不起作用,我不确定原因。以下是我的Lazy专栏的代码

@Composable
fun DisplayTasks(
    tasks: List<ToDoTask>,
    onSwipeToDelete: (Action, ToDoTask) -> Unit,
    navigateToTaskScreen: (Int) -> Unit
) {
    LazyColumn {
        items(
            items = tasks,
            key = { task ->
                task.id
            }
        ) { task ->
            val dismissState = rememberDismissState()
            val dismissDirection = dismissState.dismissDirection
            val isDismissed = dismissState.isDismissed(DismissDirection.EndToStart)

            if (isDismissed && dismissDirection == DismissDirection.EndToStart
            ) {
                val scope = rememberCoroutineScope()
                scope.launch {
                    delay(300)
                    onSwipeToDelete(Action.DELETE, task)
                }
            }

            AnimatedVisibility(
                visible = !isDismissed,
                exit = shrinkVertically(
                    animationSpec = tween(
                        durationMillis = 300,
                    )
                ),
                enter = expandVertically(
                    animationSpec = tween(
                        durationMillis = 300
                    )
                )
            ) {
                SwipeToDismiss(
                    state = dismissState,
                    directions = setOf(DismissDirection.EndToStart),
                    dismissThresholds = { FractionalThreshold(0.2f) },
                    background = { RedBackground() },
                    dismissContent = {
                        LazyColumnItem(
                            toDoTask = task,
                            navigateToTaskScreen = navigateToTaskScreen
                        )
                    }
                )
            }
        }
    }

}

推荐答案

首先,您不应该在Composable内执行任何状态更改操作。取而代之的是使用一种副作用,通常是LaunchedEffect(key) { }:块的内容将在第一次渲染时被调用,并且每次关键点与最后一次渲染不同。此外,在内部,您已经在一个协程作用域,所以没有必要启动它。有关副作用的更多信息,请参阅documentation

列表中的项目动画为not yet supported。只需向项目中添加AnimatedVisibility即可。

当Compose第一次在撰写树中看到AnimatedVisibility时,它在没有动画的情况下绘制(或不绘制)它。

当下一次重新合成visible不同于上次渲染时间时,它会生成动画。

因此,要使其按您希望的方式工作,您可以执行以下操作:

  1. 添加itemAppeared状态值,列表中的项目最初会被隐藏,渲染后使用副作用使其立即可见
  2. 添加columnAppeared将阻止初始外观动画-如果没有它,在屏幕渲染时,所有项目都将显示得太生动
@Composable
fun DisplayTasks(
    tasks: List<ToDoTask>,
    onSwipeToDelete: (Action, ToDoTask) -> Unit,
) {
    var columnAppeared by remember { mutableStateOf(false) }
    LaunchedEffect(Unit) {
        columnAppeared = true
    }
    LazyColumn {
        items(
            items = tasks,
            key = { task ->
                task.id
            }
        ) { task ->
            val dismissState = rememberDismissState()
            val dismissDirection = dismissState.dismissDirection
            val isDismissed = dismissState.isDismissed(DismissDirection.EndToStart)
            if (isDismissed && dismissDirection == DismissDirection.EndToStart
            ) {
                LaunchedEffect(Unit) {
                    delay(300)
                    onSwipeToDelete(Action.DELETE, task)
                }
            }

            var itemAppeared by remember { mutableStateOf(!columnAppeared) }
            LaunchedEffect(Unit) {
                itemAppeared = true
            }
            AnimatedVisibility(
                visible = itemAppeared && !isDismissed,
                exit = shrinkVertically(
                    animationSpec = tween(
                        durationMillis = 300,
                    )
                ),
                enter = expandVertically(
                    animationSpec = tween(
                        durationMillis = 300
                    )
                )
            ) {
                SwipeToDismiss(
                    state = dismissState,
                    directions = setOf(DismissDirection.EndToStart),
                    dismissThresholds = { FractionalThreshold(0.2f) },
                    background = {
                        Box(
                            Modifier
                                .background(Color.Red)
                                .fillMaxSize()
                        )
                    },
                    dismissContent = {
                        Text(task.id)
                    }
                )
            }
        }
    }
}

这篇关于AnimatedVisibility&amp;SwipeToDismisse输入动画不会触发-Jetpack Compose的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-03 05:33