您可以使用Side Effects 观察任何状态。如果您需要等待某个操作完成,您可以使用if + DisposableEffect:
if (swipeableState.isAnimationRunning) {
DisposableEffect(Unit) {
onDispose {
println("animatin finished")
}
}
}
动画开始时,我创建一个DisposableEffect,结束时,onDispose被调用,表示动画结束。
对于您的代码,这也会在启动时触发,因为当您在onSizeChanged 之后更改锚点时,这也会启动动画。但是你可以检查一下这个值是不是变了,所以问题不大。
要解决你的基本问题,你还需要有左、中、右三种状态。
有点题外话,关于那条线:
val width = if (size.value.width == 0f) 1f else size.value.width - 60.dp.value * 2
- 您每次重构时都重复此计算,您不应该这样做。您可以使用
LaunchedEffect 和size.value.width 作为键,因为width 只需要在该值更改时重新计算。
- 您试图通过乘以 2 从 DP 中获取像素值。这是错误的,您需要使用 Dencity。
所以最终的代码可以是这样的:
enum class SwipeDirection(val raw: Int) {
Left(0),
Initial(1),
Right(2),
}
@Composable
fun TestScreen() {
var size by remember { mutableStateOf(Size.Zero) }
val swipeableState = rememberSwipeableState(SwipeDirection.Initial)
val density = LocalDensity.current
val boxSize = 60.dp
val width = remember(size) {
if (size.width == 0f) {
1f
} else {
size.width - with(density) { boxSize.toPx() }
}
}
val scope = rememberCoroutineScope()
if (swipeableState.isAnimationRunning) {
DisposableEffect(Unit) {
onDispose {
when (swipeableState.currentValue) {
SwipeDirection.Right -> {
println("swipe right")
}
SwipeDirection.Left -> {
println("swipe left")
}
else -> {
return@onDispose
}
}
scope.launch {
// in your real app if you don't have to display offset,
// snap without animation
// swipeableState.snapTo(SwipeDirection.Initial)
swipeableState.animateTo(SwipeDirection.Initial)
}
}
}
}
Box(
modifier = Modifier
.fillMaxWidth()
.onSizeChanged { size = Size(it.width.toFloat(), it.height.toFloat()) }
.clickable { }
.swipeable(
state = swipeableState,
anchors = mapOf(
0f to SwipeDirection.Left,
width / 2 to SwipeDirection.Initial,
width to SwipeDirection.Right,
),
thresholds = { _, _ -> FractionalThreshold(0.3f) },
orientation = Orientation.Horizontal
)
.background(Color.LightGray)
) {
Box(
Modifier
.offset { IntOffset(swipeableState.offset.value.roundToInt(), 0) }
.size(boxSize)
.background(Color.DarkGray)
)
}
}
结果:
附言如果您在滑动过程中不需要为任何内容设置动画,我已将此逻辑移至separate modifier。