For a android.widget.Button I can use performClick() to simulate a click programmatically. But I don't know how to do it in Jetpack Compose. I've looked into the compose.material documentation but I at least coudn't find anything about this.
4 Answers
With this solution you will get the ripple effect programmatically like you have pressed the button:
1) Create interactionSource:
val interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
2) Create coroutine scope:
val coroutine = rememberCoroutineScope()
3) In your button set interaction source:
Button(
onClick = {
vm.myFunction()
},
//important
interactionSource = interactionSource,
.
.
.
)
4) Finally call it like so from anywhere:
coroutine.launch {
val press = PressInteraction.Press(Offset.Zero)
interactionSource.emit(press)
vm.myFunction()
delay(300)
interactionSource.emit(PressInteraction.Release(press))
}
3 Comments
onClick is not invoked. HmmonClick method to be called when the button appears as clicked. There is no scenario in which I don't want that onClick to be called when the button appears as clicked.In compose you're creating a button with action. You can pass action function and call same function programmatically.
// you need to remember your callback to prevent extra recompositions.
// pass all variables that may change between recompositions
// as keys instead of `Unit`
val onClickAction = remember(Unit) {
{
// do some action
}
}
LaunchedEffect(Unit) {
// perform action in 1 sec after view appear
delay(1000)
onClickAction()
}
Button(
onClick = onClickAction
) {
Text(text = "Button")
}
6 Comments
onClick but with extra steps?LaunchedEffect is needed here because you can't call side effects directly from the view builder. Also it gives you a coroutine scope, so you can call delay and other suspend functions easily. Check out more in documentation. And remember is needed to prevent extra recompositions as I've mentioned in the commentperformClick I can call a Button just like I would have pressed it with my finger. I could have no idea what that button does. I have a Compose Button from a library that I have made and I don't have access to its OnClickListener. I just need to press it, but not with my finger, just using the code. performClick also triggers the ripple effect.I'd write an instrumentation test with ComposeTestRule for this. performClick() generally works as expected for me on a SemanticNodeInteraction object.
I did run into a problem where it only worked when the element was currently visible though, so I needed to call performScrollTo() first:
composeTestRule.onNode(...).run {
performScrollTo()
performClick()
}
Comments
A very simple solution for that.
Create a state variable
val verifyNumberOnClick = remember { mutableStateOf(false) }Create a private function that can be used as an action for onClick.
private fun makeSum(a: Int, b: Int){ Log.e("Atiar", "Sum of a & b: ${a+b}") }Create
if-elseto run that function.if (verifyNumberOnClick.value){ makeSum(5,6) verifyNumberOnClick.value = false }You are done. now it's your time to change the value of
verifyNumberOnClicktotrue.
from anywhere, you will make it true your function will be called. means you can perform onclick tasks from anywhere.
as sample you can change the value of verifyNumberOnClick from button on click.
Button(
onClick = {verifyNumberOnClick.value = false}
) {
Text(text = "Button")
}
onClickinstead of simulating a click?onClickmethods but then I would not have the ripple effect, nor the sound.performClick, but maybe you could look into UI testing for Compose: developer.android.com/jetpack/compose/testing