CoilZoomAsyncImage自定义下滑关闭手势跟缩放手势冲突,加了下滑关闭后,缩放不灵敏
补充一下,因为图片浏览器通常都带有进入的动画,比如从消息流的图片cell原始rect,慢慢放大到全屏。这个时候zoomState.zoomable.transform.scaleX会从原始rect的1慢慢变大,所以当处于图片预览页的时候,这个scaleX就已经不是1了。如果根据finalRect.width/startRect.width去计算,确实也能解决这个问题。不过不太优雅,建议在动画期间不要改这个zoomState.zoomable.transform.scaleX
zoomState.zoomable.transform 是当前总的缩放信息,zoomState.zoomable.baseTransform 是基础缩放信息,由 scaleType 决定,zoomState.zoomable.userTransform 是由用户产生的缩放信息,所以你判断 userTransform 即可
zoomState.zoomable.transform 是当前总的缩放信息,zoomState.zoomable.baseTransform 是基础缩放信息,由 scaleType 决定,zoomState.zoomable.userTransform 是由用户产生的缩放信息,所以你判断 userTransform 即可
多谢,是否处于scaling状态的问题是解决了。但是遇到了新的问题,就是没有处于缩放状态的时候下滑手势跟缩放手势出现了冲突。导致缩放不灵敏
val dragGesture = rememberDraggableState { delta ->
// 仅在非多点触控时处理拖拽
if (!isMultiTouch) {
val canDrag =
when {
// up
delta < 0 -> offsetY > -boundaryThreshold
// down
delta > 0 -> offsetY < boundaryThreshold
else -> false
}
if (canDrag) {
offsetY += delta
isDragging = true
}
onOffsetChange(offsetY)
}
}
val onDragEnd = { velocity: Float ->
isDragging = false
val velocityThreshold = 1000f
val shouldDismiss =
when {
abs(velocity) > velocityThreshold -> true
abs(offsetY) > screenHeight * maxFactor -> true
else -> false
}
if (shouldDismiss) {
wrappedOnDismiss()
} else {
offsetY = 0f
// Reset opacity to 1 when drag is cancelled
alpha = 1f
onOpacityChange(alpha)
}
onDragEnd(shouldDismiss)
}
// Calculate the parallax translation
// As the page moves away from center, shift the image in the opposite direction
// This creates the parallax effect where background moves slower than foreground
// val imageTranslation = pageOffset * screenWidth.value * parallaxFactor
val zoomState = rememberCoilZoomState()
debug(TAG, "zoomState:${zoomState.zoomable.userTransform.scaleX}")
isZooming = zoomState.zoomable.userTransform.scaleX != 1.0f
// LaunchedEffect(zoomState.zoomable) {
// zoomState.zoomable.disabledGestureTypes =
// zoomState.zoomable.disabledGestureTypes or
// GestureType.ONE_FINGER_SCALE or
// GestureType.MOUSE_WHEEL_SCALE or
// GestureType.KEYBOARD_SCALE
// }
Card(
modifier = Modifier.fillMaxSize(),
shape = RectangleShape,
colors = CardDefaults.cardColors(containerColor = Color.Transparent),
) {
Box(modifier = Modifier.fillMaxSize()) {
CoilZoomAsyncImage(
model = ImageRequest.Builder(LocalContext.current).data(imageUrl).crossfade(true).build(),
contentDescription = null,
zoomState = zoomState,
scrollBar = null,
onTap = { onTap() },
modifier =
Modifier.fillMaxSize()
.graphicsLayer { translationX = pageOffset }
.then(
if (isZooming) {
Modifier
} else {
Modifier
// 添加触摸事件检测器,优先于draggable,在触摸开始时检测是单指还是多指
.pointerInput(Unit) {
awaitPointerEventScope {
while (true) {
val event = awaitPointerEvent()
// 检测多点触控
isMultiTouch = event.changes.size > 1
debug(
TAG,
"Touch event: ${event.changes.size} fingers, isMultiTouch=$isMultiTouch",
)
}
}
}
.offset { IntOffset(0, animatedOffsetY.value.roundToInt()) }
.draggable(
state = dragGesture,
orientation = Orientation.Vertical,
onDragStarted = {
// 仅在非多点触控时启动拖拽
if (!isMultiTouch) {
isDragging = true
onDragStart()
}
},
onDragStopped = { velocity ->
// 仅在非多点触控时处理拖拽结束
if (!isMultiTouch) {
onDragEnd(velocity)
}
},
)
}
),
)
}
}
大佬帮忙看下这个下滑拖拽手势怎么跟缩放手势并存,目前只要加了draggable缩放就很不灵敏。试过禁用掉ONE_FINGER_SCALE依然不好使
这个我没有实践过,没法指导你,只能说一下整体的思路
首先从 Down 开始你就要拦截全部事件,然后判断当前是否处于可以关闭的状态,以及手势是否要是关闭手势,是的话继续自己消费后续事件处理关闭,不是的话就释放后续事件让 ZoomImage 消费,这其中会涉及到很多细节,需要你一个个解决
这个我没有实践过,没法指导你,只能说一下整体的思路
首先从 Down 开始你就要拦截全部事件,然后判断当前是否处于可以关闭的状态,以及手势是否要是关闭手势,是的话继续自己消费后续事件处理关闭,不是的话就释放后续事件让 ZoomImage 消费,这其中会涉及到很多细节,需要你一个个解决
按照你的思路,我应该修改源码的哪一部分。我尝试过直接在awaitPointerEventScope拦截事件,但是事件依然会先被CoilZoomAsyncImage消费掉