https://kotlinlang.org logo
#compose
Title
# compose
f

Francois Morvillier

03/09/2021, 8:16 PM
Hi! Does Compose have a simple or idiomatic way to create a button which calls an onPressed function every N milliseconds as long as it remains pressed?
Here is what I ended up doing:
Copy code
private val dispatcherScope = GlobalScope

@Composable
fun PressAndHoldTextButton(text: String,
                           modifier: Modifier = Modifier,
                           fontSize: TextUnit = TextUnit.Unspecified,
                           fontStyle: FontStyle? = null,
                           fontWeight: FontWeight? = null,
                           fontFamily: FontFamily? = null,
                           enabled: Boolean = true,
                           backgroundColor: Color = Color.Unspecified,
                           onPressed: () -> Unit,
                           delayBeforeRepeatInMs: Long = 500L,
                           repeatPeriodInMs: Long = 30L,
) {
    var pressTimestamp by remember { mutableStateOf(0L) }

    val bkgColor by animateColorAsState(targetValue = if (pressTimestamp!=0L) backgroundColor.copy(alpha = 1f) else backgroundColor)

    Box(modifier = modifier
        .background(bkgColor)
        .pointerInteropFilter { event ->
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    if (enabled) {
                        pressTimestamp = System.currentTimeMillis()
                        val timestampForThisPress = pressTimestamp
                        onPressed()
                        dispatcherScope.launch {
                            delay(delayBeforeRepeatInMs)
                            while (pressTimestamp == timestampForThisPress) {
                                onPressed()
                                delay(repeatPeriodInMs)
                            }
                        }
                    }
                }
                MotionEvent.ACTION_UP -> {
                    pressTimestamp = 0L
                }
                else -> {
                }
            }
            true
        }
    ) {
        Text(text = text,
            fontSize = fontSize,
            fontStyle = fontStyle,
            fontWeight = fontWeight,
            fontFamily = fontFamily,
            textAlign = TextAlign.Center,
            modifier = modifier.wrapContentSize(Alignment.Center)
        )
    }
}