1

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

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

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

基本上我想要的是检测诸如 KeyUp 和 KeyDown 事件之类的东西。

如何做到这一点?

4

3 回答 3

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"
)
于 2021-10-17T01:22:47.960 回答
0

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

Modifier.pointerInput(Unit) {
    detectTapGestures(
        onPress = { /* Called when the gesture starts */ },
        onDoubleTap = { /* Called on Double Tap */ },
        onLongPress = { /* Called on Long Press */ },
        onTap = { /* Called on Tap */ }
    )
}
于 2021-10-16T18:35:31.080 回答
0

Modifier.pointerInput在我的Icon.

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

根据文档,

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

于 2021-10-17T05:49:43.473 回答