输入、手势与语义 · AndroidX 源码指南
AAndroidX 源码指南
Compose UI
Compose 底层 · androidx.compose.ui

输入、手势与语义1.13.0-alpha01

pointerInput 处理原始手势,semantics 让操作可访问且可测试。

最后更新 2026-08-01

优先使用高层交互

按钮、clickabletoggleable 已经组合了点击、键盘、焦点、语义和视觉 indication。只有需要自定义手势竞争或原始指针数据时才进入 pointerInput

Modifier.pointerInput(Unit) {
    detectTapGestures(
        onLongPress = { position -> showMenu(position) },
    )
}

常用手势检测器

检测器用途
detectTapGestures点击/双击/长按
detectDragGestures拖拽(onDragStart/onDrag/onDragEnd)
detectTransformGestures捏合缩放/旋转/平移
awaitPointerEventScope原始指针事件循环
Modifier.pointerInput(Unit) {
    detectDragGestures { change, dragAmount ->
        change.consume()
        offset += dragAmount
    }
}

key 改变时 pointer input handler 会取消并重启。handler 内应遵守协程取消,不能把阻塞操作放在事件循环里。

手势能用不代表辅助技术能用

pointerInput 不会自动声明”这是按钮”。自定义操作必须补齐语义,或更好地从已有高层 modifier 组合:

复制即用

Modifier.semantics {
    contentDescription = "播放"
    role = Role.Button
    onClick {
        play()
        true
    }
}

语义规范

  • 语义树是 Compose UI 测试定位和断言的基础。
  • 不要给已有 Text 再重复设置相同 contentDescription,否则屏幕阅读器可能朗读两遍。
  • 自定义可点击元素记得 role + onClick,否则 TalkBack 不识别。

常见陷阱

  • 纯 pointerInput 没语义:辅助技术/测试找不到节点。
  • 重复 contentDescription:屏幕阅读器朗读两遍。
  • 阻塞事件循环:pointerInput 内做阻塞操作,手势会卡。
  • 忘 consume 事件change.consume() 不调用,手势会传递到父级。

要点

  • 高层交互(clickable/toggleable)已含语义,优先使用。
  • 自定义手势才进 pointerInput;key 变则重启。
  • 自定义操作必须补齐 semantics(role + onClick)。
  • 语义树也是 UI 测试定位基础。

相关页面