我试图使用画布和detectDragGestures方法画直线,但到目前为止,我只实现了没有任何固定的混乱行为.我正在寻找一个解决方案来确保我的线条始终笔直.

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun CanvasAction() {
    var centerOffset by remember {
        mutableStateOf(Offset.Zero)
    }

    var points by remember {
        mutableStateOf<List<Point>>(listOf())
    }

    Canvas(
        modifier = Modifier
            .fillMaxSize()
            .pointerInput(key1 = Unit) {
                detectDragGestures(
                    onDragStart = { offset ->
                        points = points + Point(offset = offset, isStartedPosition = true)
                    },
                    onDrag = { change, offset ->
                        change.historical.forEach {
                            centerOffset = it.position
                        }

                        points = points + change.historical.map {
                            Point(offset = it.position, isStartedPosition = false)
                        }
                    },
                )
            },
    ) {
        drawCircle(
            color = Color.Blue,
            radius = 7.dp.toPx(),
            center = centerOffset,
        )

        val path = Path()

        points.forEach { point ->
            if (point.isStartedPosition) {
                path.moveTo(point.offset.x, point.offset.y)
            } else {
                path.lineTo(point.offset.x, point.offset.y)
            }
        }

        drawPath(
            path = path,
            color = Color.Blue,
            style = Stroke(width = 2.dp.toPx()),
        )
    }
}

my example

推荐答案

问题是您在拖动操作期间保存了每个点.

如果您只记住onDragStart期间的起点,并在onDrag期间计算current点,同时忽略任何中间点,则您可以在这两点之间绘制一条路径,并且始终保持直线.

如果您想对多个拖动手势重复此操作,同时保留之前的行,则需要使用onDragEnd来保存当前行.

它可能看起来像这样:

@Composable
fun CanvasAction() {
    var centerOffset by remember {
        mutableStateOf<Offset?>(null)
    }

    var finishedLines by remember {
        mutableStateOf<List<Rect>>(emptyList())
    }

    var currentLine by remember {
        mutableStateOf<Rect?>(null)
    }

    Canvas(
        modifier = Modifier
            .fillMaxSize()
            .pointerInput(key1 = Unit) {
                detectDragGestures(
                    onDragStart = { offset ->
                        centerOffset = offset
                        currentLine = Rect(offset, offset)
                    },
                    onDrag = { _, dragAmount ->
                        centerOffset = centerOffset?.plus(dragAmount)
                        currentLine = currentLine?.let {
                            it.copy(
                                right = it.right + dragAmount.x,
                                bottom = it.bottom + dragAmount.y,
                            )
                        }
                    },
                    onDragEnd = {
                        centerOffset = null
                        currentLine?.let { finishedLines += it }
                        currentLine = null
                    },
                    onDragCancel = {
                        centerOffset = null
                        currentLine = null
                    },
                )
            },
    ) {
        centerOffset?.let {
            drawCircle(
                color = Color.Blue,
                radius = 7.dp.toPx(),
                center = it,
            )
        }

        val linesToDraw = currentLine?.let { finishedLines + it } ?: finishedLines
        val path = Path()

        linesToDraw.forEach {
            path.moveTo(it.left, it.top)
            path.lineTo(it.right, it.bottom)
        }

        drawPath(
            path = path,
            color = Color.Blue,
            style = Stroke(width = 2.dp.toPx()),
        )
    }
}

为了表示一条线,我使用了一个具有两个偏置坐标的androidx.compose.ui.geometry.Rect,我使用这些坐标来保存线的起点和终点;不再使用Point类.finishedLines是已经绘制的所有线的列表,其中currentLine是目前is绘制的线.

其他更改主要针对当前没有绘制任何内容时的空处理.

Android相关问答推荐

如何允许我的应用程序在Android 10上运行,同时目标是API 33

Jetpack Compose Scaffold—content不在TopAppBar下面开始'

如何在Jetpack导航中不显示目的地?

原因平滑滚动的滞后懒惰列在android jetpack compose

添加可组合元素的列表?

在内部创建匿名对象的繁忙循环调用函数会产生开销吗?

如何判断堆肥是否为空?

安卓Azure通讯聊天UI库导入?

Jetpack Compose的val变量不能被重新分配

当父布局的背景为浅色时,Android ProgressBar 背景 colored颜色 变为灰色

Jetpack compose (Glance) 小部件在加载位图图像后不会重新组合

在 theme.xml 中使用 android:autoCompleteTextViewStyle

是否可以在 Kotlin 中为 mutableStateOf() 设置自定义设置器

缺少类 com.google.android.datatransport.runtime.ForcedSender

使用 capacitor cordova 插件的 Android Studio 错误

如何在jetpack compose中创建水印文字效果

我的 react native 项目的发布签名 apk 没有在设备中打开,而且它创建的尺寸非常小

Android - 水平(从右到左)圆形背景 colored颜色 过渡

react-native android项目未找到错误

如何满足设备内框架的无效 Wear OS 屏幕截图Wear OS 表盘策略违规?