代码之家  ›  专栏  ›  技术社区  ›  Arpit Shukla

如何在compose中检测软键事件?

  •  1
  • Arpit Shukla  · 技术社区  · 4 年前

    我试图创建一个图标按钮,当点击时,它会调用lambda,但是如果用户按下按钮并按住它,那么lambda也会在固定的时间间隔内被连续调用。

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

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

    基本上我想要的是检测像KeyUp和KeyDown事件这样的东西。

    如何做到这一点?

    0 回复  |  直到 4 年前
        1
  •  1
  •   Francesc    4 年前

    你可以用 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
  •  0
  •   Richard Onslow Roper    4 年前

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

    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
  •  0
  •   Arpit Shukla    4 年前

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

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

    根据文件,

    onPress 当检测到压力机并 PressGestureScope.tryAwaitRelease 可用于检测指针何时释放或手势何时取消。