HRJ*_*HRJ 5 android android-jetpack-compose
我可以使用 很好地检测变换手势Modifier.detectTransformGesture(),如下面的简化示例所示:
Box(
Modifier
.pointerInput(Unit) {
detectTransformGestures(
onGesture = { _, pan, gestureZoom, gestureRotate ->
// do something
}
)
}
)
Run Code Online (Sandbox Code Playgroud)
但我想知道用户何时完成手势,以便我可以执行更多(计算密集型)操作。
我找不到任何线索。我尝试使用Modifier.transformableand TransformableStatewhich 确实有一个名为 的属性isTransformInProgress,但我不知道如何在回调中访问它:
val state = rememberTransformableState {
// How do I access state.isTransformInProgress ?
}
// I can access it here
Text(if(state.isTransformInProgress) "transforming" else "not transforming")
Run Code Online (Sandbox Code Playgroud)
如果使用时需要检查转换结束Modifier.transformable,可以isTransformInProgress使用LaunchedEffect:
val state = rememberTransformableState {
}
LaunchedEffect(state.isTransformInProgress) {
if (!state.isTransformInProgress) {
// do what you need
}
}
Run Code Online (Sandbox Code Playgroud)
我可以想到两种变体,都是在研究源代码后得出的:
detectTransformGestures并行订阅事件:fun Modifier.pointerInputDetectTransformGestures(
panZoomLock: Boolean = false,
isTransformInProgressChanged: (Boolean) -> Unit,
onGesture: (centroid: Offset, pan: Offset, zoom: Float, rotation: Float) -> Unit
): Modifier {
return pointerInput(Unit) {
detectTransformGestures(
panZoomLock = panZoomLock,
onGesture = { offset, pan, gestureZoom, gestureRotate ->
isTransformInProgressChanged(true)
onGesture(offset, pan, gestureZoom, gestureRotate)
}
)
}
.pointerInput(Unit) {
forEachGesture {
awaitPointerEventScope {
awaitFirstDown(requireUnconsumed = false)
do {
val event = awaitPointerEvent()
val canceled = event.changes.any { it.consumed.positionChange }
} while (!canceled && event.changes.any { it.pressed })
isTransformInProgressChanged(false)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
pointerInputDetectTransformGestures(它没有内部引用),并在那里添加所需的逻辑,如下所示:suspend fun PointerInputScope.detectTransformGestures(
panZoomLock: Boolean = false,
onGesture: (centroid: Offset, pan: Offset, zoom: Float, rotation: Float) -> Unit,
isTransformInProgressChanged: (Boolean) -> Unit,
) {
forEachGesture {
awaitPointerEventScope {
var rotation = 0f
var zoom = 1f
var pan = Offset.Zero
var pastTouchSlop = false
val touchSlop = viewConfiguration.touchSlop
var lockedToPanZoom = false
var startGestureNotified = false // added
awaitFirstDown(requireUnconsumed = false)
do {
val event = awaitPointerEvent()
val canceled = event.changes.fastAny { it.positionChangeConsumed() }
if (!canceled) {
val zoomChange = event.calculateZoom()
val rotationChange = event.calculateRotation()
val panChange = event.calculatePan()
if (!pastTouchSlop) {
zoom *= zoomChange
rotation += rotationChange
pan += panChange
val centroidSize = event.calculateCentroidSize(useCurrent = false)
val zoomMotion = abs(1 - zoom) * centroidSize
val rotationMotion = abs(rotation * PI.toFloat() * centroidSize / 180f)
val panMotion = pan.getDistance()
if (zoomMotion > touchSlop ||
rotationMotion > touchSlop ||
panMotion > touchSlop
) {
pastTouchSlop = true
lockedToPanZoom = panZoomLock && rotationMotion < touchSlop
}
}
if (pastTouchSlop) {
val centroid = event.calculateCentroid(useCurrent = false)
val effectiveRotation = if (lockedToPanZoom) 0f else rotationChange
if (effectiveRotation != 0f ||
zoomChange != 1f ||
panChange != Offset.Zero
) {
onGesture(centroid, panChange, zoomChange, effectiveRotation)
if (!startGestureNotified) { // notify first gesture sent
isTransformInProgressChanged(true)
startGestureNotified = true
}
}
event.changes.fastForEach {
if (it.positionChanged()) {
it.consumeAllChanges()
}
}
}
}
} while (!canceled && event.changes.fastAny { it.pressed })
isTransformInProgressChanged(false) // notify last finger is up
}
}
}
Run Code Online (Sandbox Code Playgroud)
无论如何,您都必须检查新版本的 compose 中的任何更改才能更新您的代码(不知道它的可能性有多大)。
使用第二种方法至少您可以确定它不会崩溃,因为您不依赖于它们的实现。
| 归档时间: |
|
| 查看次数: |
2954 次 |
| 最近记录: |