I have a composable component like so:
Card(
modifier = Modifier
.fillMaxWidth()
.then(modifier ?: Modifier),
backgroundColor = colorResource(id = R.color.Red),
shape = RoundedCornerShape(percent = 50),
) {
Row (
modifier = Modifier
.size(160.dp)
) {
}
}
When the user clicks and holds the Card
I want to check if the user has held the Card for a second. If they held it longer than a second then I want to log "CLICKED" but if they let go before a second then don't log "CLICKED"
How can I achieve this?
This can be done by writing a custom gesture Modifier such as
fun Modifier.timedClick(
timeInMillis: Long,
interactionSource: MutableInteractionSource = remember {MutableInteractionSource()},
onClick: (Boolean) -> Unit
) = composed {
var timeOfTouch = -1L
LaunchedEffect(key1 = timeInMillis, key2 = interactionSource) {
interactionSource.interactions
.onEach { interaction: Interaction ->
when (interaction) {
is PressInteraction.Press -> {
timeOfTouch = System.currentTimeMillis()
}
is PressInteraction.Release -> {
val currentTime = System.currentTimeMillis()
onClick(currentTime - timeOfTouch > timeInMillis)
}
is PressInteraction.Cancel -> {
onClick(false)
}
}
}
.launchIn(this)
}
Modifier.clickable(
interactionSource = interactionSource,
indication = rememberRipple(),
onClick = {}
)
}
Usage
val context = LocalContext.current
Card(
shape = RoundedCornerShape(percent = 50),
) {
Box(
modifier = Modifier
.timedClick(
timeInMillis = 1000,
) { passed: Boolean ->
Toast
.makeText(
context,
"Pressed longer than 1000 $passed",
Toast.LENGTH_SHORT
)
.show()
}
.fillMaxWidth()
.height(100.dp),
contentAlignment = Alignment.Center
) {
Text("Hello World")
}
}
Result