commonMain.androidx.compose.material.DragGestureDetectorCopy.kt Maven / Gradle / Ivy
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.compose.material
// Copy-paste version of DragGestureDetector.kt. Please don't change this file without changing
// DragGestureDetector.kt
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.pointer.AwaitPointerEventScope
import androidx.compose.ui.input.pointer.PointerEvent
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.PointerId
import androidx.compose.ui.input.pointer.PointerInputChange
import androidx.compose.ui.input.pointer.PointerType
import androidx.compose.ui.input.pointer.changedToUpIgnoreConsumed
import androidx.compose.ui.platform.ViewConfiguration
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastFirstOrNull
import kotlin.math.abs
import kotlin.math.sign
internal suspend fun AwaitPointerEventScope.awaitHorizontalPointerSlopOrCancellation(
pointerId: PointerId,
pointerType: PointerType,
onPointerSlopReached: (change: PointerInputChange, overSlop: Float) -> Unit
) = awaitPointerSlopOrCancellation(
pointerId = pointerId,
pointerType = pointerType,
onPointerSlopReached = onPointerSlopReached,
getDragDirectionValue = { it.x }
)
private suspend inline fun AwaitPointerEventScope.awaitPointerSlopOrCancellation(
pointerId: PointerId,
pointerType: PointerType,
onPointerSlopReached: (PointerInputChange, Float) -> Unit,
getDragDirectionValue: (Offset) -> Float
): PointerInputChange? {
if (currentEvent.isPointerUp(pointerId)) {
return null // The pointer has already been lifted, so the gesture is canceled
}
val touchSlop = viewConfiguration.pointerSlop(pointerType)
var pointer: PointerId = pointerId
var totalPositionChange = 0f
while (true) {
val event = awaitPointerEvent()
val dragEvent = event.changes.fastFirstOrNull { it.id == pointer }!!
if (dragEvent.isConsumed) {
return null
} else if (dragEvent.changedToUpIgnoreConsumed()) {
val otherDown = event.changes.fastFirstOrNull { it.pressed }
if (otherDown == null) {
// This is the last "up"
return null
} else {
pointer = otherDown.id
}
} else {
val currentPosition = dragEvent.position
val previousPosition = dragEvent.previousPosition
val positionChange = getDragDirectionValue(currentPosition) -
getDragDirectionValue(previousPosition)
totalPositionChange += positionChange
val inDirection = abs(totalPositionChange)
if (inDirection < touchSlop) {
// verify that nothing else consumed the drag event
awaitPointerEvent(PointerEventPass.Final)
if (dragEvent.isConsumed) {
return null
}
} else {
onPointerSlopReached(
dragEvent,
totalPositionChange - (sign(totalPositionChange) * touchSlop)
)
if (dragEvent.isConsumed) {
return dragEvent
} else {
totalPositionChange = 0f
}
}
}
}
}
private fun PointerEvent.isPointerUp(pointerId: PointerId): Boolean =
changes.fastFirstOrNull { it.id == pointerId }?.pressed != true
private val mouseSlop = 0.125.dp
private val defaultTouchSlop = 18.dp // The default touch slop on Android devices
private val mouseToTouchSlopRatio = mouseSlop / defaultTouchSlop
internal fun ViewConfiguration.pointerSlop(pointerType: PointerType): Float {
return when (pointerType) {
PointerType.Mouse -> touchSlop * mouseToTouchSlopRatio
else -> touchSlop
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy