Ely*_*lye 7 android android-jetpack-compose
在正常情况下,我们可以有 onTouchEvent
override fun onTouchEvent(event: MotionEvent?): Boolean {
when (event?.action) {
MotionEvent.ACTION_DOWN -> {}
MotionEvent.ACTION_MOVE -> {}
MotionEvent.ACTION_UP -> {}
else -> return false
}
invalidate()
return true
}
Run Code Online (Sandbox Code Playgroud)
在 Jetpack Compose 中,我只能发现我们有tapGestureFilterin 修饰符,它只执行来自ACTION_UPonly的动作。
Modifier
.tapGestureFilter { Log.d("Track", "Tap ${it.x} | ${it.y}") }
.doubleTapGestureFilter { Log.d("Track", "DoubleTap ${it.x} | ${it.y}") }
Run Code Online (Sandbox Code Playgroud)
onTouchEventJetpack Compose是否有等价物?
Thr*_*ian 28
pointerInteropFilter如果您不使用 touch api 与现有视图代码进行互操作,则未将其描述为首选使用方式。
一个特殊的 PointerInputModifier,提供对最初调度到 Compose 的底层 MotionEvent 的访问。优先选择pointerInput,并且仅将其用于与使用MotionEvents 的现有代码的互操作。虽然此修饰符的主要目的是允许任意代码访问分派给 Compose 的原始 MotionEvent,但为了完整性,提供了类似物以允许任意代码与系统交互,就好像它是 Android 视图一样。
您可以使用pointerInput 、awaitTouchDownfor MotionEvent.ACTION_DOWN、awaitPointerEventforMotionEvent.ACTION_MOVE和MotionEvent.ACTION_UP
val pointerModifier = Modifier
.pointerInput(Unit) {
awaitEachGesture {
awaitFirstDown()
// ACTION_DOWN here
do {
//This PointerEvent contains details including
// event, id, position and more
val event: PointerEvent = awaitPointerEvent()
// ACTION_MOVE loop
// Consuming event prevents other gestures or scroll to intercept
event.changes.forEach { pointerInputChange: PointerInputChange ->
pointerInputChange.consumePositionChange()
}
} while (event.changes.any { it.pressed })
// ACTION_UP is here
}
}
Run Code Online (Sandbox Code Playgroud)
关于手势的一些要点
detectorDragGestures源码实例
val down = awaitFirstDown(requireUnconsumed = false)
var drag: PointerInputChange?
var overSlop = Offset.Zero
do {
drag = awaitPointerSlopOrCancellation(
down.id,
down.type
) { change, over ->
change.consumePositionChange()
overSlop = over
}
} while (drag != null && !drag.positionChangeConsumed())
Run Code Online (Sandbox Code Playgroud)
所以当你需要阻止其他事件拦截时
调用pointerInputChange.consumeDown()after awaitFirstDown,调用pointerInputChange.consumePositionChange() afterawaitPointerEvent
并且awaitFirstDown()有requireUnconsumed默认为 true 的参数。如果你将其设置为 false,即使pointerInput 在你的手势之前消耗殆尽,你仍然会得到它。这也是像拖动这样的事件如何利用它来首先下降的方式。
您看到的每个可用事件detectDragGestures,
detectTapGestures甚至awaitFirstDown用于awaitPointerEvent
实现,因此使用awaitFirstDown和使用更改您可以配置自己的手势。awaitPointerEvent
例如,这是我从原始版本定制的函数,detectTransformGestures仅使用特定数量的向下指针来调用。
suspend fun PointerInputScope.detectMultiplePointerTransformGestures(
panZoomLock: Boolean = false,
numberOfPointersRequired: Int = 2,
onGesture: (centroid: Offset, pan: Offset, zoom: Float, rotation: Float) -> Unit,
) {
forEachGesture {
awaitPointerEventScope {
var rotation = 0f
var zoom = 1f
var pan = Offset.Zero
var pastTouchSlop = false
val touchSlop = viewConfiguration.touchSlop
var lockedToPanZoom = false
awaitFirstDown(requireUnconsumed = false)
do {
val event = awaitPointerEvent()
val downPointerCount = event.changes.size
// If any position change is consumed from another pointer or pointer
// count that is pressed is not equal to pointerCount cancel this gesture
val canceled = event.changes.any { it.positionChangeConsumed() } || (
downPointerCount != numberOfPointersRequired)
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)
}
event.changes.forEach {
if (it.positionChanged()) {
it.consumeAllChanges()
}
}
}
}
} while (!canceled && event.changes.any { it.pressed })
}
}
}
Run Code Online (Sandbox Code Playgroud)
从1.2.0-beta01开始,不推荐使用部分消耗,例如
PointerInputChange.consemePositionChange()、
PointerInputChange.consumeDownChange()和用于消耗所有更改的消耗PointerInputChange.consumeAllChanges()
PointerInputChange.consume()
Run Code Online (Sandbox Code Playgroud)
是唯一用于防止其他手势/事件的方法。
我这里还有一个教程,详细介绍了手势
Yur*_*sap 12
我们有一个单独的包,这非常有用。有两个主要的扩展功能适合您:
如果您想处理和处理事件,我建议使用pointerInteropFilter它的类似物View.onTouchEvent. 它与modifier以下一起使用:
Column(modifier = Modifier.pointerInteropFilter {
when (it.action) {
MotionEvent.ACTION_DOWN -> {}
MotionEvent.ACTION_MOVE -> {}
MotionEvent.ACTION_UP -> {}
else -> false
}
true
})
Run Code Online (Sandbox Code Playgroud)
这将是根据您指定的View.onTouchEvent示例编写调整后的代码。
PS 不要忘记@ExperimentalPointerInput注释。
| 归档时间: |
|
| 查看次数: |
1368 次 |
| 最近记录: |