增加双击放大图片功能

This commit is contained in:
amos wong
2025-12-29 23:23:42 +08:00
parent 84b31ddf45
commit 935139814b

View File

@@ -42,6 +42,7 @@ import androidx.compose.animation.core.tween
import androidx.compose.animation.core.LinearEasing
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.snapshots.SnapshotStateMap
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -1018,6 +1019,9 @@ private fun ZoomableImage(
var offsetX by remember { mutableFloatStateOf(0f) }
var offsetY by remember { mutableFloatStateOf(0f) }
// 双击检测
var lastTapTime by remember { mutableLongStateOf(0L) }
// 通知父组件缩放状态变化
LaunchedEffect(scale) {
onScaleChanged(scale)
@@ -1030,6 +1034,8 @@ private fun ZoomableImage(
awaitEachGesture {
// 等待第一个手指按下
val firstDown = awaitFirstDown(requireUnconsumed = false)
val downTime = System.currentTimeMillis()
val downPosition = firstDown.position
var pointerId = firstDown.id
var isTap = true
@@ -1053,48 +1059,78 @@ private fun ZoomableImage(
}
}
// 缩放状态下的单指拖动
if (changes.size == 1 && scale > 1f) {
val change = changes.first()
val dragAmount = change.position - change.previousPosition
if (dragAmount.getDistance() > 2f) {
isTap = false
offsetX += dragAmount.x
offsetY += dragAmount.y
// 限制拖动范围
val maxOffsetX = (scale - 1f) * size.width / 2
val maxOffsetY = (scale - 1f) * size.height / 2
offsetX = offsetX.coerceIn(-maxOffsetX, maxOffsetX)
offsetY = offsetY.coerceIn(-maxOffsetY, maxOffsetY)
change.consume()
}
}
// 检查是否所有手指都抬起
if (changes.all { !it.pressed }) {
// 单指点击且没有移动太多
if (isTap && !isMultiTouch) {
if (scale > 1f) {
scale = 1f
offsetX = 0f
offsetY = 0f
val currentTime = System.currentTimeMillis()
val timeSinceLastTap = currentTime - lastTapTime
if (timeSinceLastTap < 300) {
// 双击 - 切换缩放
if (scale > 1f) {
scale = 1f
offsetX = 0f
offsetY = 0f
} else {
scale = 2.5f
}
lastTapTime = 0L
} else {
onTap()
// 可能是单击,记录时间等待判断
lastTapTime = currentTime
}
}
break
}
// 单指移动时检查是否移动太多(判断是否为点击)
if (changes.size == 1 && !isMultiTouch) {
if (changes.size == 1 && !isMultiTouch && scale <= 1f) {
val change = changes.first()
val moved = (change.position - change.previousPosition).getDistance()
if (moved > 10f) {
isTap = false
// 单指滑动不消费事件,让 Pager 处理
}
}
}
}
}
.pointerInput(Unit) {
detectTapGestures(
onDoubleTap = {
if (scale > 1f) {
scale = 1f
offsetX = 0f
offsetY = 0f
} else {
scale = 2.5f
}
}
)
},
contentAlignment = Alignment.Center
) {
// 延迟处理单击关闭
LaunchedEffect(lastTapTime) {
if (lastTapTime > 0) {
kotlinx.coroutines.delay(300)
if (System.currentTimeMillis() - lastTapTime >= 300) {
if (scale > 1f) {
scale = 1f
offsetX = 0f
offsetY = 0f
} else {
onTap()
}
lastTapTime = 0L
}
}
}
AsyncImage(
model = imageUrl,
contentDescription = null,