【问题标题】:How to detect motion events on a compose button?如何检测撰写按钮上的运动事件?
【发布时间】:2021-10-16 14:15:56
【问题描述】:

我正在尝试创建一个图标按钮,该按钮在点击时调用 lambda,但如果用户按下按钮并按住它,那么 lambda 也应该以固定的时间间隔连续调用。

@Composable
fun MyIconButton(
    someLambda: () -> Unit
) {
    IconButton(onClick = someLambda) {
        Icon(
            // painter and content description
        )
    }
}

我想要的是,当用户按下按钮时,someLambda 应该被调用(工作正常)。此外,我还想重复调用someLambda(两次调用之间的间隔为 500 毫秒),直到用户释放按钮。

基本上我想要检测 KeyUp 和 KeyDown 事件。

如何做到这一点?

【问题讨论】:

  • 最好检查一次...您可能会有所了解stackoverflow.com/questions/65835642/…
  • 谢谢你的链接,我去看看。
  • 哦,你是佩里。
  • @ArpitShukla。我不明白。在某个地方你说你只想要一个按钮来执行基于按下和长按的不同代码块,然后你突然引入键盘和箭头键? A.) 您见过哪个 Android 键盘包含箭头键,其次,键盘是从哪里输入图片的?你不想要一个可组合按钮?
  • 其实不然,'key'这个词还是让人迷惑。为什么不直接说如何在 Compose 中检测 Button 上的运动事件

标签: android kotlin android-jetpack-compose android-jetpack-compose-text


【解决方案1】:

您可以为此使用Modifier.pointerInpteropFilter

var job by remember {
    mutableStateOf<Job?>(null)
}
val scope = rememberCoroutineScope()

Icon(
    imageVector = Icons.Filled.Favorite,
    modifier = Modifier
        .requiredSize(96.dp)
        .pointerInteropFilter {
            when (it.action) {
                MotionEvent.ACTION_DOWN -> {
                    job = scope.launch {
                        while (true) {
                            // trigger event
                            Log.d("foo", "Trigger event")
                            delay(500L)
                        }
                    }
                }
                MotionEvent.ACTION_UP,
                MotionEvent.ACTION_CANCEL -> {
                    job?.cancel()
                    job = null
                }
            }
            true
        },
    contentDescription = "Sample icon"
)

另一种解决方案是使用Modifier.pointerInput:

val scope = rememberCoroutineScope()
Icon(
    imageVector = Icons.Filled.Favorite,
    modifier = Modifier
        .requiredSize(96.dp)
        .pointerInput(Unit) {
            while (true) {
                awaitPointerEventScope {
                    awaitFirstDown()
                    val job = scope.launch {
                        while (true) {
                            // trigger event
                            Log.d("foo", "Trigger event")
                            delay(500L)
                            Log.d("foo", "After delay")
                        }
                    }
                    waitForUpOrCancellation()
                    job.cancel()
                }
            }
        },
    contentDescription = "Sample icon"
)

【讨论】:

    【解决方案2】:

    我会在明天更新答案,但现在,这应该适合你的用例

    Modifier.pointerInput(Unit) {
        detectTapGestures(
            onPress = { /* Called when the gesture starts */ },
            onDoubleTap = { /* Called on Double Tap */ },
            onLongPress = { /* Called on Long Press */ },
            onTap = { /* Called on Tap */ }
        )
    }
    

    【讨论】:

    • 但是等等,佩里在哪里?
    【解决方案3】:

    我在我的Icon 上使用这个Modifier.pointerInput 解决了这个问题。

    Modifier.pointerInput(true) {
        detectTapGestures(onPress = {
            coroutineScope {
                val job = launch {
                    while (true) {
                        // Invoke lambda
                        delay(500)
                    }
                }
                tryAwaitRelease()
                job.cancel()
            }
        })
    }
    

    根据文档,

    onPress 在检测到按下时调用,PressGestureScope.tryAwaitRelease 可用于检测指针何时释放或手势被取消。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-22
      • 1970-01-01
      • 1970-01-01
      • 2013-01-10
      • 1970-01-01
      • 1970-01-01
      • 2015-10-07
      • 2013-12-05
      相关资源
      最近更新 更多