【问题标题】:Reset offset animation on draggable item in Jetpack Compose在 Jetpack Compose 中重置可拖动项目上的偏移动画
【发布时间】:2021-04-28 16:51:46
【问题描述】:

我有一个可以垂直拖动的绿色方块。但是每当我停止拖动它时,我希望它用动画将偏移量重置为开始。我试过这样,但我无法弄清楚。有人知道怎么做吗?

@Composable
fun DraggableSquare() {
    var currentOffset by remember { mutableStateOf(0F) }
    val resetAnimation by animateIntOffsetAsState(targetValue = IntOffset(0, currentOffset.roundToInt()))

    var shouldReset = false

    Box(contentAlignment = Alignment.TopCenter, modifier = Modifier.fillMaxSize()) {
        Surface(
            color = Color(0xFF34AB52),
            modifier = Modifier
                .size(100.dp)
                .offset {
                    when {
                        shouldReset -> resetAnimation
                        else -> IntOffset(0, currentOffset.roundToInt())
                    }
                }
                .draggable(
                    state = rememberDraggableState { delta -> currentOffset += delta },
                    orientation = Orientation.Vertical,
                    onDragStopped = {
                        shouldReset = true
                        currentOffset = 0F
                    }
                )
        ) {}
    }
}

【问题讨论】:

    标签: android kotlin animation drag android-jetpack-compose


    【解决方案1】:

    您可以将偏移量定义为Animatable
    拖动时使用snapTo方法更新当前值作为初始值,onDragStopped开始动画。

    val coroutineScope = rememberCoroutineScope()
    val offsetY  =  remember { Animatable(0f) }
    
    Box(contentAlignment = Alignment.TopCenter, modifier = Modifier.fillMaxSize()) {
        Surface(
            color = Color(0xFF34AB52),
            modifier = Modifier
                .size(100.dp)
                .offset {
                    IntOffset(0, offsetY.value.roundToInt())
                }
                .draggable(
                    state = rememberDraggableState { delta ->
                        coroutineScope.launch {
                            offsetY.snapTo(offsetY.value + delta)
                        }
                    },
                    orientation = Orientation.Vertical,
                    onDragStopped = {
                        coroutineScope.launch {
                            offsetY.animateTo(
                                targetValue = 0f,
                                animationSpec = tween(
                                    durationMillis = 3000,
                                    delayMillis = 0
                                )
                            )
                        }
                    }
                )
        ) {
        }
    }
    

    【讨论】:

    • 很好,这修复了重置部分,但我也希望重置以流畅的动画进行。这可能吗?
    • @DonnyRozendal 我已经更新了添加动画的答案。
    • 您先生是真正的英雄,谢谢!真的很干净,可读。我的另一个解决方案涉及创建竞争条件的多个状态,因此将所有内容放在一个 Animatable 中是可行的方法。我也有这个想法,但不想为拖动设置动画。但我看到你用snapTo 解决了这个问题,真是天才。
    • 另外,在snapTo 函数内部,它应该是offsetY 而不是offsetX。但我无法请求编辑,因为它没有足够的字符。
    • @DonnyRozendal 感谢您的反馈。我已经更新了答案。
    猜你喜欢
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-06
    • 1970-01-01
    相关资源
    最近更新 更多