如何改进目前在Kotlin中使用函数扩展的代码



我希望在新的坐标系中放置一条线,新的原点坐标是val orig=Point(100,50),新的X轴在右边,新的Y轴在上面。

目前,我使用功能扩展,就像代码A一样。

我发现它不好,有很多重复的代码,比如.toX(orig).toY(orig)

如何设计数据结构来改进代码

代码A

val orig=Point(100,50)
drawIntoCanvas {
it.drawLine(
Offset(x = 0f.toX(orig), y = 0f.toY(orig)),
Offset(x = (size.width- 200).toX(orig), y = 0f.toY(orig)),
axisPaint
)

val shadowPath = Path()
val data =  maxCountList.toList()
val step= 20       
for (i in data.indices){
shadowPath.lineTo((orignX+step*i).toX(orig),data[i].toFloat().toY(orig))
}
shadowPath.close()
it.drawPath(shadowPath,pathPaint)

it.nativeCanvas.drawText("Max",50f.toX(orig), 100f.toY(orig), textPaint)
}

fun Float.toX(originCoordinate: Point) : Float {
return originCoordinate.x+this
}
fun Float.toY(originCoordinate: Point): Float {
return originCoordinate.y-this
}

结束

我可以将委托传递给Kotlin中的变量吗?是完美的解决方案!

data class MyPoint(val x: Float, val y: Float) {
val Float.toXX: Float get() = x + this
val Float.toYY: Float get() = y - this
}
// In a function:
val orig = MyPoint(size.width / 2, size.height / 2)
orig.run {
drawPath.moveTo(10.0f.toXX, 20.0f.toYY)
drawPath.moveTo(5.0f.toXX, 80.0f.toYY)
drawPath.moveTo(1.0f.toXX, 3.0f.toYY)
}

我想说,最简单的方法是在绘图时,通过翻译画布,使的原点成为画布的实际原点:

fun Canvas.withTranslation(x: Float, y: Float, block: (Canvas) -> Unit) {
withSave {
translate(x, y)
block(this)
}
}
fun DrawScope.drawIntoCanvasWithOrigin(origin: PointF, block: (Canvas) -> Unit) {
drawIntoCanvas {
it.withTranslation(origin.x, origin.y) { canvas ->
block(canvas)
}
}
}

然后,您不需要将原点添加到每一个值,因为所有的东西都已经相对于您的原点,您只需写:

val orig=Point(100,50)
drawIntoCanvasWithOrigin(orig.toPointF()) {
it.drawLine(
Offset(x = 0f, y = 0f),
Offset(x = size.width- 200, y = 0f),
axisPaint
)

val shadowPath = Path()
val data =  maxCountList.toList()
val step= 20       
for (i in data.indices){
shadowPath.lineTo(orignX+step*i,data[i].toFloat())
}
shadowPath.close()
it.drawPath(shadowPath,pathPaint)

it.nativeCanvas.drawText("Max",50f, 100f, textPaint)
}

考虑到您的意见,即您希望在定义的原点镜像y轴,我们可以相应地扩展代码:

fun Canvas.withScale(x: Float, y: Float, block: (Canvas) -> Unit) {
withSave {
scale(x, y)
block(this)
}
}
fun DrawScope.drawIntoCanvasWithOrigin(origin: PointF, block: (Canvas) -> Unit) {
drawIntoCanvas {
it.withTranslation(origin.x, origin.y) { canvasAtOrigin ->
canvasAtOrigin.withScale(1.0f, -1.0f) { mirroredCanvas ->
block(mirroredCanvas)
}
}
}
}

我认为扩展函数并不能真正提高可读性。我要做的不是关注x和y,而是关注点。二维布局中的偏移是一个新的点,所以你最好做这样的事情:

fun Point.offset(offsetX: Float, offsetY: Float): Point {
return Point(this.x + offsetX, this.y + offsetY)
}

你这样使用它:

it.drawLine(
orig.offset(0f, 0f),   // which is of course the same as: orig
orig.offset(size.width - 200f, 0f),
axisPaint
)

我想这个问题和答案有点主观,但在我看来,扩展没有添加任何内容。实际上使它变得不必要的复杂。

只是写

it.drawLine(
Offset(x = orig.x + 0f, y = orig.y + 0f),
Offset(x = orig.x + (size.width- 200), y = orig.y - 0f),
axisPaint
)

在我看来更好。也没有必要添加0f,所以在这个例子中,我只使用

it.drawLine(
Offset(x = orig.x, y = orig.y),
Offset(x = orig.x + (size.width- 200), y = orig.y),
axisPaint
)

最新更新