ame*_*cle 6 kotlin android-jetpack-compose
我目前正在尝试实现在可组合项可缩放、可平移(拖动表面)或两者之间切换的选项。到目前为止,有效的方法是切换相应的按钮,以达到预期的结果。不起作用的是切换一个按钮与另一个按钮 - 这会产生保留第一个按钮功能的意外结果。例如,假设缩放处于活动状态。当我按下平移按钮时,背景突出显示会相应变化,所有测试日志都显示预期状态 - 但表面仍然可缩放,不可拖动。我首先必须手动禁用缩放。关于为什么会发生这种情况有什么想法吗?
Modifier.run {
if (zoomEnabled) {
this.pointerInput(Unit) {
detectTransformGestures { _, _, zoom, _ ->
passScale(zoom)
}
}
} else if (panEnabled) {
this.pointerInput(Unit) {
detectDragGestures { change, dragAmount ->
change.consumeAllChanges()
passOffsetX(dragAmount.x / 3)
passOffsetY(dragAmount.y / 3)
}
}
} else
this
}
Run Code Online (Sandbox Code Playgroud)
纽扣:
@Composable
fun TopBarAction(
zoomEnabled: Boolean,
passZoomEnabled: (Boolean) -> Unit,
panEnabled: Boolean,
passPanEnabled: (Boolean) -> Unit
) {
IconToggleButton(
checked = zoomEnabled,
onCheckedChange = {
passPanEnabled(false)
passZoomEnabled(it)
},
modifier = Modifier
.background(
if (zoomEnabled) Color.LightGray else Color.Transparent,
shape = CircleShape
),
enabled = true
) {
Icon(...)
}
IconToggleButton(
checked = panEnabled,
onCheckedChange = {
passZoomEnabled(false)
passPanEnabled(it)
},
modifier = Modifier
.background(
if (panEnabled) Color.LightGray else Color.Transparent,
shape = CircleShape
),
enabled = true
) {
Icon(...)
}
}
Run Code Online (Sandbox Code Playgroud)
使用普通的 .pointerInput 修饰符和内部条件而不是 run 根本无法识别任何输入,并且 detectorTransformGesture 的 pan 没有按照我需要的方式运行(尽管如果其他所有方法都失败,这可能是我将使用的)
第一个问题是 PointerInput 使用一个或多个键创建一个闭包,并使用旧值,除非您设置的键发生变化。
您需要相应地设置键。
第二个问题是,即使您设置了键, detectorDragGestures 或 detectorTransformGestures 也会消耗事件,因此如果第一个已经消耗了事件,则上面的 PointerInputChange 将无法获取它。
它consume()
的作用是通过返回Offset.Zero、trueconsumeAllChanges()
来阻止其上方或父级上的 pointInput 接收事件。由于拖动、滚动或变换手势会检查 PointeInputChange.isConsumed 是否为 true,因此如果您在之前的pointerInput 中使用它们,它们将永远不会收到任何事件。PointeInputChange.positionChange()
PointerInputChange.isConsumed
例如拖动源代码
suspend fun PointerInputScope.detectDragGestures(
onDragStart: (Offset) -> Unit = { },
onDragEnd: () -> Unit = { },
onDragCancel: () -> Unit = { },
onDrag: (change: PointerInputChange, dragAmount: Offset) -> Unit
) {
forEachGesture {
awaitPointerEventScope {
val down = awaitFirstDown(requireUnconsumed = false)
var drag: PointerInputChange?
var overSlop = Offset.Zero
do {
drag = awaitPointerSlopOrCancellation(
down.id,
down.type
) { change, over ->
change.consume()
overSlop = over
}
// ! EVERY Default GESTURE HAS THIS CHECK
} while (drag != null && !drag.isConsumed)
if (drag != null) {
onDragStart.invoke(drag.position)
onDrag(drag, overSlop)
if (
!drag(drag.id) {
onDrag(it, it.positionChange())
it.consume()
}
) {
onDragCancel()
} else {
onDragEnd()
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以链接 Modifier.pointerInput() 而不是使用 Modifier.run
Modifier
.pointerInput(keys){
// Gesture scope1
if(zoomEnabled){...}
}
.pointerInput(keys){
// Gesture scope2
if(panEnabled){
....
}
}
Run Code Online (Sandbox Code Playgroud)
事件首先进入手势范围 2,然后进入手势范围 1
创建了一个小示例,您可以观察手势如何变化和传播以及它们如何使用按键重置
@Composable
private fun MyComposable() {
var zoomEnabled by remember { mutableStateOf(false) }
var dragEnabled by remember { mutableStateOf(false) }
var text by remember { mutableStateOf("") }
Column() {
val modifier = Modifier
.size(400.dp)
.background(Color.Red)
.pointerInput(zoomEnabled) {
if (zoomEnabled) {
detectTransformGestures { centroid, pan, zoom, rotation ->
println("ZOOOMING")
text = "ZOOMING centroid: $centroid"
}
}
}
.pointerInput(key1 = dragEnabled, key2= zoomEnabled) {
if (dragEnabled && !zoomEnabled) {
detectDragGestures { change, dragAmount ->
println("DRAGGING")
text = "DRAGGING $dragAmount"
}
}
}
Box(modifier = modifier)
Text(text = text)
OutlinedButton(onClick = { zoomEnabled = !zoomEnabled }) {
Text("zoomEnabled: $zoomEnabled")
}
OutlinedButton(onClick = { dragEnabled = !dragEnabled }) {
Text("dragEnabled: $dragEnabled")
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用上面的答案和片段创建自己的行为。
归档时间: |
|
查看次数: |
1365 次 |
最近记录: |