我正在try 有一个带有一些尾随文本的复选框.其 idea 是,无论您 Select 的是复选框本身,还是文本,值都会被切换.为了代码简洁,我在Composable中做了所有的事情.

在 Select 文本时,它会按预期工作.但当我特别按下复选框时,没有任何react .我看到了按下复选框的连锁react ,但它显然忽略了行的可点击功能,点击了onCheckChange = {}

我不太擅长组合作用域,所以我想这可能是因为Row()是一个内联函数,所以我try 对Surface应用相同的修饰符,但也不起作用.

两个地点打同样的电话没什么大不了的,我只想知道为什么.

@Composable
fun CheckboxInRowWithText() {
    var checkedState by remember { mutableStateOf(false) }
    Surface {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .clickable {
                    checkedState = !checkedState
                },
            verticalAlignment = Alignment.CenterVertically) {
            Checkbox(checked = checkedState, onCheckedChange = {} )

            Text(text = "Clicking this Row will toggle checkbox")
        }
    }
}

推荐答案

你不能点击一个祖先合成物的原因不是因为它在另一个下面,默认情况下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)
    }
}

结果

enter image description here

点击传播样本

你可以点击下面的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的父级,没有消费调用,结果为

enter image description here

@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")
        }
    }
}

Android相关问答推荐

derivedStateOf与使用key和MutableState记住

如何将结果从viewModelScope传递到活动

使用Retrofit2的API调用:我如何能够一直进行API调用,以更新数据而无需重新打开应用程序

如何在Android Jetpack Compose中找到我的手机屏幕一行有多少个单词

StateFlow集合AsState没有更新他的值Jetpack Compose导航

登录方法显示为空列表,即使它显示的是Firebase身份验证控制台

第一次使用onBackPressed()、NavigateUp()加载时MapView崩溃

LaunchedEffect没有延迟时应用程序崩溃

Android 中 recyclerview 的自定义分隔线 colored颜色 不起作用

Android Drawable文件夹中的图像显示模糊

当 EditText 用于在 android studio 中将字符串发送到 firebase 时,仅允许安全调用错误

Android 访问任意公共目录

为什么@PrimaryKey val id: Int? = null 在创建 Room 实体时有效吗?

Android Studio电鳗:javaHome好像无效

组成不重叠的元素

Int 传递给 Intent 但Android工作室说我传递了一个字符串

GridLayout 和 GridView 有什么好用和区别

插入查询室 OnConflictStrategy.REPLACE

如何在 kotlin 的 android room DB 中设置一对多关系

ObjectBox,如何在冲突中放弃一切迁移?