Mag*_*cka 5 android kotlin android-jetpack-compose
我在撰写时遇到问题。我尝试实现简单的日历。我已经显示了月份,并启用了通过箭头更改月份。
现在我想通过滑动添加更改月份。我尝试过.swipeable
这是示例:
val size = remember { mutableStateOf(Size.Zero) }
val swipeableState = rememberSwipeableState(0)
val width = if (size.value.width == 0f) 1f else size.value.width - 60.dp.value * 2
Box(
modifier = Modifier
.fillMaxWidth()
.onSizeChanged { size.value = Size(it.width.toFloat(), it.height.toFloat()) }
.swipeable(
state = swipeableState,
anchors = mapOf(0f to 0, width to 1),
thresholds = { _, _ -> FractionalThreshold(0.3f) },
orientation = Orientation.Horizontal
)
.background(Color.LightGray)
) {
Box(
Modifier
.offset { IntOffset(swipeableState.offset.value.roundToInt(), 0) }
.size(60.dp)
.background(Color.DarkGray)
)
}
Run Code Online (Sandbox Code Playgroud)
但这并不完美。我需要保留在日历区域之外,并且我不知道如何更改月份状态(响应显示日历)。
我的问题是“如果我想在滑动后调用操作,如何实现滑动”。
Phi*_*hov 14
您可以通过Side Effects观察任何状态。如果您需要等待操作完成,可以使用if+ DisposableEffect:
if (swipeableState.isAnimationRunning) {
DisposableEffect(Unit) {
onDispose {
println("animation finished")
}
}
}
Run Code Online (Sandbox Code Playgroud)
当动画开始时,我创建一个DisposableEffect,当它结束时,onDispose被调用,这意味着动画完成。
对于您的代码,这也会在启动时触发,因为当您在 之后更改锚点时onSizeChanged,这也会启动动画。但你可以检查该值是否已更改,因此问题不大。
为了解决你的基本问题,你还需要有三种状态:左、中、右。
关于这句话,有点题外话:
val width = if (size.value.width == 0f) 1f else size.value.width - 60.dp.value * 2
Run Code Online (Sandbox Code Playgroud)
rememeberwithsize.value.width作为键,因为width只有当该值发生变化时才需要重新计算。所以最终的代码可以如下所示:
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)
)
}
}
Run Code Online (Sandbox Code Playgroud)
结果:

ps 如果您在滑动过程中不需要设置任何动画,我已将此逻辑移至单独的修改器中。
| 归档时间: |
|
| 查看次数: |
7074 次 |
| 最近记录: |