你不能点击一个祖先合成物的原因不是因为它在另一个下面,默认情况下touch 传播从一个后代传到另一个祖先,因为PointerEventPass是Main.
Modifier.clickable不允许父对象获取事件的原因是,它调用PointerEventChange.consume
,但您可以编写自己的单击函数来从子对象传播到父对象、从父对象传播到子对象或有条件地消费.
更多详细信息,你可以查看this answer
你基本上什么都没做.这就是为什么它不变的原因,把check kedState设置在onCheckedChange
以内.
@Composable
fun CheckboxInRowWithText() {
val context = LocalContext.current
var checkedState by remember { mutableStateOf(false) }
Surface {
Row(
modifier = Modifier
.fillMaxWidth()
.clickable {
Toast
.makeText(context, "Row clicked", Toast.LENGTH_SHORT)
.show()
checkedState = !checkedState
},
verticalAlignment = Alignment.CenterVertically) {
Checkbox(checked = checkedState, onCheckedChange = {
Toast.makeText(context, "Checkbox check", Toast.LENGTH_SHORT).show()
checkedState = it
}
)
Text(text = "Clicking this Row will toggle checkbox")
}
}
}
此外,您可以像这样构建它,即使您单击复选框也会显示涟漪.
@Composable
fun CheckBoxWithTextRippleFullRow(
label: String,
state: Boolean,
onStateChange: (Boolean) -> Unit
) {
// Checkbox with text on right side
Row(modifier = Modifier
.fillMaxWidth()
.height(40.dp)
.clickable(
role = Role.Checkbox,
onClick = {
onStateChange(!state)
}
)
.padding(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Checkbox(
checked = state,
onCheckedChange = null
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = label)
}
}
结果
点击传播样本
你可以点击下面的Composable,即使是Button
,这是一个Surface
,引擎盖下有Modifier.clickable
.
让我们只为Button
岁以下的父母创建我们自己的定制touch
private fun Modifier.customTouch(
pass: PointerEventPass,
onDown: () -> Unit,
onUp: () -> Unit
) = this.then(
Modifier.pointerInput(pass) {
awaitEachGesture {
awaitFirstDown(pass = pass)
onDown()
waitForUpOrCancellation(pass)
onUp()
}
}
)
并将其分配给具有PointerEventPass.Initial的父级,没有消费调用,结果为
@Preview
@Composable
private fun LookAheadLayoutTest() {
val context = LocalContext.current
Box(
modifier = Modifier
.customTouch(
pass = PointerEventPass.Initial,
onDown = {
Toast
.makeText(context, "Parent down", Toast.LENGTH_SHORT)
.show()
}, onUp = {
Toast
.makeText(context, "Parent up", Toast.LENGTH_SHORT)
.show()
}
)
.padding(bottom = 50.dp)
.fillMaxSize()
.padding(20.dp),
contentAlignment = Alignment.BottomCenter
) {
Button(
onClick = {
Toast.makeText(context, "Button is clicked", Toast.LENGTH_SHORT).show()
}) {
Text("Click Button")
}
}
}