如何在Jetpack Compose按钮上检测按压事件实现长按重复触发回调
实现方案
核心思路是通过pointerInput修饰符监听触摸的按下/抬起事件,配合协程的循环定时调用实现重复触发,同时保留原有单击逻辑,完整实现代码如下:
import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.input.pointer.pointerInput import kotlinx.coroutines.delay import kotlinx.coroutines.launch @Composable fun MyIconButton( someLambda: () -> Unit, repeatIntervalMs: Long = 500 // 可自定义重复触发间隔,默认500ms ) { // 标记用户是否处于按压状态 var isPressed by remember { mutableStateOf(false) } // 监听按压状态,触发重复调用 LaunchedEffect(isPressed) { if (isPressed) { // 按压状态下循环调用回调 while (true) { someLambda() delay(repeatIntervalMs) } } } IconButton( onClick = someLambda, modifier = Modifier.pointerInput(Unit) { awaitPointerEventScope { while (true) { // 监听按下事件 awaitPointerEvent() isPressed = true try { // 监听抬起/取消事件(比如用户滑出按钮区域) awaitPointerEvent() } finally { isPressed = false } } } } ) { Icon( // 你原有Icon的painter和contentDescription配置 ) } }
核心逻辑说明
- 用
remember存储isPressed状态,实时同步用户的按压状态 pointerInput修饰符监听触摸全流程:按下时标记按压状态为真,触摸抬起或者触摸取消(用户滑出按钮区域)时标记状态为假LaunchedEffect监听isPressed变化,按压状态为真时启动无限协程循环,每隔指定间隔调用一次传入的lambda;按压状态变为假时协程会自动取消,循环终止- 完全保留原有
IconButton的onClick逻辑,单击场景的触发不受任何影响
可选优化:增加首次触发延迟
如果需要避免轻触按钮时误触发重复调用,可以给首次重复调用增加前置延迟,修改LaunchedEffect逻辑即可:
LaunchedEffect(isPressed) { if (isPressed) { // 按住后先延迟300ms再开始重复调用,可自定义时长 delay(300) while (true) { someLambda() delay(repeatIntervalMs) } } }
内容的提问来源于stack exchange,提问作者Arpit Shukla
相关产品推荐
相关产品推荐

