如何在 Android Jetpack Compose 中检测按钮按下后的按钮释放?

问题描述 投票:0回答:7

我找到了

onClick
onLongClick
甚至
onPress
的监听器,但是没有像
buttonDown
buttonUp
onPress
onRelease
这样的事件/监听器。

我错过了什么吗?我当前的用例是,当用户按下按钮时,我会增加计数,当用户释放按钮时,我会减少计数。但总的来说,我希望用户按下按钮后就开始发生一些事情,并在用户释放按钮时停止。 (举个现实生活中的例子,看看 Facebook Messenger 如何录制视频,按住按钮即可开始,松开按钮后视频就会停止。

我在 Android 上使用 Jetpack Compose。

android android-jetpack-compose android-jetpack android-compose-button android-jetpack-compose-button
7个回答
12
投票

您可以使用

InteractionSource.collectIsPressedAsState
来了解按钮是否被按下。 您可以添加副作用来了解按钮何时被释放。

类似:

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")
}


5
投票
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
        }
    )
}

3
投票

这些代码可能对你有帮助

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()


                        }

2
投票

使用.pointerInput修饰符:

.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
投票
                    .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
投票

如果您想在按下按钮时以特定的时间间隔执行操作,您可以使用以下代码(改编自Gabriele的答案)。此示例会在长按时自动增加值。

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

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

val coroutineScope = rememberCoroutineScope()

if (isPressed) {
    var job: Job? = null

    LaunchedEffect(Unit) {
        currentStateTxt = "Pressed"
        currentCount += 1
        job = coroutineScope.launch {
            delay(500)
            while (isActive) { // Coroutine is only cancellable at this line
                currentCount += 1
                delay(150)
            }
        }
    }

    DisposableEffect(Unit) {
        onDispose {
            job?.cancel()
            currentStateTxt = "Released"
        }
    }
}

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

-1
投票

我认为你在按钮上使用触摸监听器,它可以轻松检测按钮触摸或未触摸示例

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

}

此链接中触摸监听器的更多信息Android触摸监听器

© www.soinside.com 2019 - 2024. All rights reserved.