在正常视图中,我们可以有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
}
在Jetpack Compose中,我只能找到修饰符中的tabGestureFilter
,它只从ACTION_UP
中获取操作。
Modifier
.tapGestureFilter { Log.d("Track", "Tap ${it.x} | ${it.y}") }
.doubleTapGestureFilter { Log.d("Track", "DoubleTap ${it.x} | ${it.y}") }
Jetpack Compose是否有等效的onTouchEvent
?
也许有点晚了,但由于compose一直在更新,我今天就是这样做的:
Modifier
.pointerInput(Unit) {
detectTapGestures {...}
}
.pointerInput(Unit) {
detectDragGestures { change, dragAmount -> ...}
})
我们还有<code>探测权限</code>和<code>探测权限
ps: 1.0.0-贝塔03
如果您没有使用与现有视图代码互操作的touch api,则<code>pointerInteropFilter</code>未被描述为首选使用方式。
一个特殊的PointerInputModifier,提供对最初分派到Compose的底层MotionEvents的访问。首选pointerInput并仅将其用于与使用MotionEvents的现有代码的互操作。虽然此修改器的主要目的是允许任意代码访问分派到Compose的原始MotionEvent,但为了完整性,提供了类似项以允许任意代码与系统交互,就好像它是Android视图一样。
您可以使用指针输入
、awaitTouchDown
进行MotionEvent.ACTION_DOWN
,并使用 awaitPointerEvent
进行MotionEvent.ACTION_MOVE
和MotionEvent.ACTION_UP
val pointerModifier = Modifier
.pointerInput(Unit) {
forEachGesture {
awaitPointerEventScope {
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
}
}
}
关于手势的一些关键说明
实例的detectDragGestures源代码
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())
因此,当您需要阻止其他事件拦截时
在< code>awaitFirstDown之后调用< code > pointerinputchange . consume down(),在< code>awaitPointerEvent之后调用pointerinputchange . consumepositionchange()
并且waitFirstDown()
有在默认情况下为true的所需未消耗
参数。如果您将其设置为false,即使指针输入在您的手势之前消耗掉,您仍然可以得到它。这也是像拖动这样的事件如何使用它来首先向下的。
您看到的每个可用事件< code > detectdraggestions 、< code > detecttapgestions 甚至< code>awaitFirstDown都使用< code>awaitPointerEvent来实现,因此使用< code>awaitFirstDown、< code>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 })
}
}
}
从 1.2.0-beta01 开始,部分使用,如 PointerInputChange.consemePositionChange()
、PointerInputChange.consumeDownChange()
和一个用于消耗所有更改的 PointerInputChange.consumeAllChanges()
已被弃用
PointerInputChange.consume()
是唯一用于防止其他手势/事件的。
另外,我这里有一个教程,详细介绍了手势
我们有一个单独的包,非常有用。有两个主要的扩展函数适合您:
指针输入
-文档 < li>
指针过滤器
-文档
如果您想处理和处理事件,我建议您使用pointerInteropFilter
,它类似于View.onTouchEvent
。它与修饰符
一起使用:
Column(modifier = Modifier.pointerInteropFilter {
when (it.action) {
MotionEvent.ACTION_DOWN -> {}
MotionEvent.ACTION_MOVE -> {}
MotionEvent.ACTION_UP -> {}
else -> false
}
true
})
这将是将调整后的代码组合到您指定的View.onTouchEvent
示例。
P、 别忘了@ExperimentalPointerInput
注释。
问题内容: 我建立了一个HTTP服务器。我正在使用下面的代码来获取请求URL,但未获取完整URL。 我只得到和。 我想获得完整的客户端请求的URL作为或。 谢谢。 问题答案: 从net / http包的文档中: 您的代码的修改后的版本: 输出示例:
问题内容: 不使用任何外部库,将网站的HTML内容提取为String的最简单方法是什么? 问题答案: 我目前正在使用此: 但不确定是否有更好的方法。
问题内容: 我对如何使用axios上传进度事件感到有些困惑。实际上,我正在将大量文件存储到AWS s3中。为此,如何获得上传进度?我需要这个功能 目前,我的发帖请求是这样的: 问题答案: Axios存储库中有一个明确的示例,说明了如何执行此操作:https : //github.com/mzabriskie/axios/blob/master/examples/upload/index.html
我知道,要获取地图,我可以使用fetchMap,但它不支持LinkedHashMap,我想保持由orderBy创建的插入顺序。 我试过了 但是字段1和字段2部分给了我以下错误。 无法解析“T”中的方法“field1” 希望有人能帮我~ 谢谢 解决方案: 基于@Lukas的回答,我尝试了几次,发现必须做到以下几点: > 在方法中,所有字段都必须有一个类型,除了那些计算的,其中添加类型会抛出在字段列表
我从服务器得到这样的响应: 但打印fetch API捕获中的err只会返回错误对象。 它打印了这个(来自谷歌浏览器): 我想得到正确的错误处理状态代码,就像服务器没有响应一样。 在这种情况下,有没有办法获取响应数据?否则,我可以尝试什么替代方案? 任何建议都将不胜感激!
问题内容: 我使用Crawljax抓取了动态网页。我可以获取当前的ID,状态和DOM。但我无法获得网站内容。任何人都可以帮助我吗? 如何获取动态/ Java脚本网页内容。 问题答案: 我们可以获取网站源代码cc.getBrowser()。getStrippedDom()); 或cc.getCurrentState()。getDocument();或 此编码是返回源代码(css / java脚本文件