Thr*_*ian 11 android android-jetpack-compose android-jetpack-compose-canvas
这是问答式的问题,因为我正在寻找使用 Jetpack Canvas 的绘图示例,但在 stackoverflow 上有问题,这个或另一个,我发现可以使用pointerInteropFilter像 View 那样的绘图onTouchEvent MotionEvent,根据文档,这是不建议的
一个特殊的 PointerInputModifier,提供对最初调度到 Compose 的底层 MotionEvent 的访问。优先选择pointerInput ,并且仅将其用于与使用MotionEvents 的现有代码的互操作。
虽然此修饰符的主要目的是允许任意代码访问分派给 Compose 的原始 MotionEvent,但为了完整性,提供了类似物以允许任意代码与系统交互,就好像它是 Android 视图一样。
Thr*_*ian 18
自从我发布这个答案以来已经有一段时间了,当我从这个问题得到反馈时,之前的答案对初学者来说有点令人困惑,所以我简化了它,这个手势的库和更多内容可以在github repo中找到。
我们需要运动状态,就像 View 的第一个一样
enum class MotionEvent {
Idle, Down, Move, Up
}
Run Code Online (Sandbox Code Playgroud)
需要空闲状态才能不将状态保留为 Up,因为如果发生任何重组,您的 Canvas 就会以 Up 状态重组,这会导致不需要的绘图甚至崩溃。
路径、当前触摸位置和触摸状态
var motionEvent by remember { mutableStateOf(MotionEvent.Idle) }
// This is our motion event we get from touch motion
var currentPosition by remember { mutableStateOf(Offset.Unspecified) }
// This is previous motion event before next touch is saved into this current position
var previousPosition by remember { mutableStateOf(Offset.Unspecified) }
Run Code Online (Sandbox Code Playgroud)
previousPosition是可选的,我使用它是因为我想 path.quadraticBezierTo在用指针移动时用 , 而不是 path.lineTo绘制平滑的线条
用于创建触摸事件的修饰符。Modifier.clipToBounds()是为了防止在 Canvas 之外绘图。
val drawModifier = Modifier
.fillMaxWidth()
.height(300.dp)
.clipToBounds()
.background(Color.White)
.pointerMotionEvents(
onDown = { pointerInputChange: PointerInputChange ->
currentPosition = pointerInputChange.position
motionEvent = MotionEvent.Down
pointerInputChange.consume()
},
onMove = { pointerInputChange: PointerInputChange ->
currentPosition = pointerInputChange.position
motionEvent = MotionEvent.Move
pointerInputChange.consume()
},
onUp = { pointerInputChange: PointerInputChange ->
motionEvent = MotionEvent.Up
pointerInputChange.consume()
},
delayAfterDownInMillis = 25L
)
Run Code Online (Sandbox Code Playgroud)
Modifier.pointerMotionEvents我为它编写的自定义手势库是 onTouchEvent 的对应项,它可以在上面的 github 存储库中找到,这里有关于手势的详细说明,如果您不想,您可以轻松构建自己的手势。View 的 onTouchEvent 上发生第一次触摸后有延迟,在我的设备上约为 16 毫秒,这是我测量的最快的,我也添加到 Compose 上的手势,因为当用户最初有非常快速的指针移动时,Canvas 无法处理向下事件。
并将此修改器应用于画布并根据当前状态和位置移动或绘制
Canvas(modifier = drawModifier) {
when (motionEvent) {
MotionEvent.Down -> {
path.moveTo(currentPosition.x, currentPosition.y)
previousPosition = currentPosition
}
MotionEvent.Move -> {
path.quadraticBezierTo(
previousPosition.x,
previousPosition.y,
(previousPosition.x + currentPosition.x) / 2,
(previousPosition.y + currentPosition.y) / 2
)
previousPosition = currentPosition
}
MotionEvent.Up -> {
path.lineTo(currentPosition.x, currentPosition.y)
currentPosition = Offset.Unspecified
previousPosition = currentPosition
motionEvent = MotionEvent.Idle
}
else -> Unit
}
drawPath(
color = Color.Red,
path = path,
style = Stroke(width = 4.dp.toPx(), cap = StrokeCap.Round, join = StrokeJoin.Round)
)
}
Run Code Online (Sandbox Code Playgroud)
完整绘图应用程序的 Github 存储库也可以在这里找到。
| 归档时间: |
|
| 查看次数: |
5424 次 |
| 最近记录: |