How to detect button release after button press in Android Jetpack Compose?

4.1k views Asked by At

I find listeners for onClick and onLongClick and even onPress but there is no event/listener for something like buttonDown and buttonUp, or onPress and onRelease.

Am I missing something? My current use case is that when a user presses a button I increment a count and when the user releases it I decrease the count. But in general I want something to start happening as soon as the user presses the button and stop when the user releases it. (For a real life example, see how Facebook Messenger records a video, you keep the button pressed to start and it stops when you release it.

I am using Jetpack Compose on Android.

6

There are 6 answers

0
bylazy On

Use .pointerInput modifier:

.pointerInput(Unit) {
            forEachGesture {
                awaitPointerEventScope {
                    awaitFirstDown()
                    //onPress actions here
                    do {
                        val event = awaitPointerEvent()
                        //Track other pointer evenst, like Drag etc...
                    } while (event.changes.any { it.pressed })
                    //onRelease actions here
                }
            }
        }
2
Gabriele Mariotti On

You can use the InteractionSource.collectIsPressedAsState to know if the Button is pressed. You can add a side effect to know when the Button is released.

Something like:

val interactionSource = remember { MutableInteractionSource() }
val isPressed by interactionSource.collectIsPressedAsState()

var currentStateTxt by remember { mutableStateOf("Not Pressed") }
var currentCount by remember { mutableStateOf(0) }

if (isPressed){
    //Pressed
    currentStateTxt = "Pressed"
    currentCount += 1

    //Use if + DisposableEffect to wait for the press action is completed
    DisposableEffect(Unit) {
        onDispose {
            //released
            currentStateTxt = "Released"
        }
    }
}

Button(onClick={},
    interactionSource = interactionSource
){
        Text("Current state = $currentStateTxt")
        Text("Count = $currentCount")
}

enter image description here

0
Yshh On
Modifier.pointerInput(Unit) {
    detectTapGestures(
        onPress = {
            //start
            val released = try {
                tryAwaitRelease()
            } catch (c: CancellationException) {
                false
            }
            if (released) {
                //ACTION_UP
            } else {
                //CANCELED
            }
        },
        onTap = {
            // onTap
        },
        onDoubleTap = {
            //onDoubleTap
        },
        onLongPress = {
            //onLongPress
        }
    )
}
0
Simranjit Singh On

I think you use Touch Listener on button , its easily detect button touch or untouch example

override fun onTouchEvent(e: MotionEvent): Boolean {
val x: Float = e.x
val y: Float = e.y

when (e.action) {
    MotionEvent.ACTION_MOVE -> {

        var dx: Float = x - previousX
        var dy: Float = y - previousY

        // reverse direction of rotation above the mid-line
        if (y > height / 2) {
            dx *= -1
        }

        // reverse direction of rotation to left of the mid-line
        if (x < width / 2) {
            dy *= -1
        }

        renderer.angle += (dx + dy) * TOUCH_SCALE_FACTOR
        requestRender()
    }
}

previousX = x
previousY = y
return true

}

More info of Touch Listener in this link Android Touch Listener

0
Victor Pozdnyakov On
                    .pointerInput(Unit) {
                        awaitEachGesture {
                            awaitFirstDown().also {
                                it.consume()
                                Timber
                                    .tag("click_events")
                                    .d("Action down")
                            }
                            val up = waitForUpOrCancellation()
                            // up is null when the pointer exits its bounds
                            up?.consume()
                            Timber
                                .tag("click_events")
                                .d("Action up or the the pointer exited its bounds")
                        }
0
SEZER OĞRAŞ On

these codes may be helpful for you

var isPressed by remember {
    mutableStateOf(false)
}

    .pointerInput(Unit) {
                detectTapGestures(
                    onPress = {
                        try {
                            isPressed = true

                                isPlaying = true
                                sampleSong.start()



                            awaitRelease()
                        }
                        finally {
                            isPressed = false
                            isPlaying = false
                            sampleSong.pause()


                        }