Search code examples
androidkotlinbuttonandroid-jetpack-composeandroid-jetpack

Jetpack Compose Android Button detect long click


How to detect a long click

    Button(
    onClick = onClick,
    interactionSource = interactionSource,
    modifier = Modifier
        .combinedClickable(
            onClick = onClick,
            onLongClick = onLongClick
        )
)

This doesn't work. onClick is required and I guess it consumes combinedClickable. I also need an interactionSource. I would rather prefer to avoid create a custom button.


Solution

  • It won't work with Button because of the same reason you can't chain Modifier.clickable{}.clickable{}

    With Button adding another Modifier.pointerInput() won't have any effect because Button is a Surface with onClick param that is assigned Modifier.clickable() already. Modifier.clickable already consumes events and not letting other Modifier.pointerInput() receiving it.

    In Jetpack Compose when there are two or more Modifier.pointerInput() chained together the one at the bottom receives event first with default pass which isPointeEventPass.Main. Since, clickable already consumes, the one you assign will never get it.

    Simplest way is to use InteractionSource and collecting it as

    @Preview
    @Composable
    private fun ButtonLongClickSample() {
    
        val context = LocalContext.current
    
        val interactionSource = remember { MutableInteractionSource() }
    
        val viewConfiguration = LocalViewConfiguration.current
    
    
        LaunchedEffect(interactionSource) {
            var isLongClick = false
    
            interactionSource.interactions.collectLatest { interaction ->
                when (interaction) {
                    is PressInteraction.Press -> {
                        isLongClick = false
                        delay(viewConfiguration.longPressTimeoutMillis)
                        isLongClick = true
                        Toast.makeText(context, "Long click", Toast.LENGTH_SHORT).show()
                    }
    
                    is PressInteraction.Release -> {
                        if (isLongClick.not()) {
                            Toast.makeText(context, "click", Toast.LENGTH_SHORT).show()
                        }
    
                    }
    
                }
            }
        }
    
    
        Button(
            onClick = {},
            interactionSource = interactionSource
        ) {
            Text("Some button")
        }
    }