1

how can I check when the gesture onlongpress ended? Anything like gestureUp or gestureEnd?

Card(colors = CardDefaults.cardColors(
            containerColor = Color(0xFF7DCEA0), Color.Black
        ),
            elevation = CardDefaults.cardElevation(defaultElevation = 2.dp),
            modifier = Modifier
                .padding(horizontal = 6.dp, vertical = 6.dp)
                .offset { IntOffset(swipeableState.offset.value.roundToInt(), 0) }
                .pointerInput(Unit){
                     detectTapGestures(
                         onLongPress = {
                            
                             mContext.startActivity(Intent(mContext, DCInfo::class.java))
                         }
                     )
                }
                .border(1.dp, SolidColor(Color(0xFF1C536F)), shape = RoundedCornerShape(15.dp))
                .fillMaxWidth(), shape = RoundedCornerShape(CornerSize(15.dp))
        )
VFarkas2023
  • 295
  • 1
  • 1
  • 8

2 Answers2

2

It can be done by adding callbacks to implementation of press and long press by writing your own PointerInputScope function.

Explained in detail how it works here, you can check out if you are interested in details.

suspend fun PointerInputScope.detectPressGestures(
    onLongPress: ((Offset) -> Unit)? = null,
    onPressStart: ((Offset) -> Unit)? = null,
    onPressEnd: (() -> Unit)? = null,
    onLongPressEnd: (() -> Unit)? = null,
) = coroutineScope {

    awaitEachGesture {
        val down = awaitFirstDown()
        down.consume()

        val downTime = System.currentTimeMillis()
        onPressStart?.invoke(down.position)

        val longPressTimeout = onLongPress?.let {
            viewConfiguration.longPressTimeoutMillis
        } ?: (Long.MAX_VALUE / 2)

        var longPressInvoked = false

        do {
            val event: PointerEvent = awaitPointerEvent()
            val currentTime = System.currentTimeMillis()

            if (!longPressInvoked && currentTime - downTime >= longPressTimeout) {
                onLongPress?.invoke(event.changes.first().position)
                longPressInvoked = true
            }

            event.changes
                .forEach { pointerInputChange: PointerInputChange ->
                    pointerInputChange.consume()
                }


        } while (event.changes.any { it.pressed })

        if (longPressInvoked) {
            onLongPressEnd?.invoke()
        } else {
            onPressEnd?.invoke()
        }

    }
}

Call it inside Modifier.pointerInput(){} as

Modifier.pointerInput(Unit) {
    detectPressGestures(
        onPressStart = {
        },
        onLongPress = {
        },
        onLongPressEnd = {
        },
        onPressEnd = {
        }
    )
}

Full implementation and demo to show color changes on events.

enter image description here

@Preview
@Composable
private fun PressCallbacks() {
    var gestureColor by remember { mutableStateOf(Color.LightGray) }
    val context = LocalContext.current

    Box(modifier = Modifier
        .size(200.dp)
        .background(gestureColor)
        .pointerInput(Unit) {
            detectPressGestures(
                onPressStart = {
                    gestureColor = Color.Yellow
                    Toast
                        .makeText(
                            context,
                            "Press Start",
                            Toast.LENGTH_SHORT
                        )
                        .show()
                },
                onLongPress = {
                    gestureColor = Color.Blue
                    Toast
                        .makeText(
                            context,
                            "Long Press!",
                            Toast.LENGTH_SHORT
                        )
                        .show()

                },
                onLongPressEnd = {
                    gestureColor = Color.Black
                    Toast
                        .makeText(
                            context,
                            "Long Press ENDS",
                            Toast.LENGTH_SHORT
                        )
                        .show()
                },
                onPressEnd = {
                    Toast
                        .makeText(
                            context,
                            "Press ENDS",
                            Toast.LENGTH_SHORT
                        )
                        .show()
                    gestureColor = Color.Cyan
                }
            )
        }
    )
}
Thracian
  • 43,021
  • 16
  • 133
  • 222
1

It is not what you are looking for but you with the onPress event you can use something like:

enum class ComponentState { Pressed, Released }

var toState by remember { mutableStateOf(ComponentState.Released) }
LaunchedEffect(toState){
    if (toState == ComponentState.Released){
        //doSomething()
    }
}

Card(
    //...
    modifier = Modifier
       //...
      .pointerInput(Unit) {
         detectTapGestures(
            onPress = {
                toState = ComponentState.Pressed
                tryAwaitRelease()
                toState = ComponentState.Released
            },
        )

){
  //...
}
Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841