I am running a simple Test on LaunchedEffect:
@Test
fun testSomeState() {
composeTestRule.setContent {
SomeComposable {
println("click $it")
}
}
composeTestRule.onNodeWithTag("Zivi")
.performClick()
.assertExists()
}
@Composable
fun SomeComposable(onClick: (Int) -> Unit) {
var someState by remember { mutableStateOf(0) }
Button(modifier = Modifier.testTag("Zivi").pointerInteropFilter {
someState = when (it.action) {
MotionEvent.ACTION_DOWN -> { 1 }
MotionEvent.ACTION_UP -> { 2 }
else -> { someState }
}
true
}, onClick = { }) {}
LaunchedEffect(someState) {
println("LaunchedEffect someState $someState") // prints "LaunchedEffect someState 0"
// and then "LaunchedEffect someState 2"
if (someState == 2) { onClick(someState) }
}
}
This works well, however, if i change Button to a Box, like this:
@Composable
fun SomeComposable(onClick: (Int) -> Unit) {
var someState by remember { mutableStateOf(0) }
Box(modifier = Modifier.testTag("Zivi").pointerInteropFilter {
someState = when (it.action) {
MotionEvent.ACTION_DOWN -> { 1 }
MotionEvent.ACTION_UP -> { 2 }
else -> { someState }
}
true
}) {}
LaunchedEffect(someState) {
println("LaunchedEffect someState $someState") // prints "LaunchedEffect someState 0"
if (someState == 2) { onClick(someState) }
}
}
Then the LaunchedEffect is not called on performClick, can anyone help me understand why?
CodePudding user response:
The box composable by default doesn't have any size so technically, when the user clicks on any portion of the screen, the event doesn't get consumed by the Box
.
You can verify this by adding a background(color = Color.Green)
modifier to your box and observe that no section of the screen gets colored green as expected.
You can fix this by setting a size
modifier for your Box
.
You can change your box implementation to this and it should work. I am using fillMaxSize
here
@Composable
fun SomeComposable(onClick: (Int) -> Unit) {
var someState by remember { mutableStateOf(0) }
Box(modifier = Modifier
.fillMaxSize()
.testTag("Zivi")
.pointerInteropFilter {
someState = when (it.action) {
MotionEvent.ACTION_DOWN -> {
1
}
MotionEvent.ACTION_UP -> {
2
}
else -> {
someState
}
}
true
}) {}
LaunchedEffect(someState) {
println("LaunchedEffect someState $someState") // prints "LaunchedEffect someState 0"
// and then "LaunchedEffect someState 2"
if (someState == 2) {
onClick(someState)
}
}
}