gpt4 book ai didi

Android LinearGradient 预分配和复用

转载 作者:太空狗 更新时间:2023-10-29 14:20:08 35 4
gpt4 key购买 nike

我一直在更新一个应用程序中的一些旧代码,该应用程序在 onDraw 中有很多重新分配的消息:

Avoid object allocations during draw/layout operations (preallocate and reuse instead).

所以我已经正确更新了所有内容,没有其他警告,除了一个。线性渐变。似乎没有方法可以在对象的实例上设置值。而且属性不是公开的,所以你不能做 linLayout.x = value;

这是我的代码,它提示上述警告(下划线 LinearGradient):

myPaintGradient.setShader(new LinearGradient(deviation,6,halfwidth,LinearGradientSize,barColorGreen, barColorRed, android.graphics.Shader.TileMode.CLAMP));

最佳答案

我刚刚解决了同样的问题,尽管使用的是 RadialGradient

如果您想在每次绘制调用时更新着色器的位置数据,您应该预先分配着色器(如 linter 提示的那样)并且您还应该预先分配一个 Matrix。着色器实例公开的唯一功能是 getLocalMatrixsetLocalMatrix

要在这里做您想做的事,您将使用 setLocalMatrix,传入一个您已对其执行了一些适当转换的 Matrix 实例。对于您的情况,我认为简单的翻译转换就可以解决问题。

正如我之前提到的,您需要预先分配一个 Matrix,并且在将其传递到 shader.setLocalMatrix 之前,您将在每个绘制循环中修改这个预先分配的矩阵

这是我如何更新 RadialGradient 着色器的 centerXcenterY 的示例。这个用例是用户可以拖动一个圆圈,我需要保持径向渐变以圆圈为中心。

下面的代码向您展示了一个完整的工作解决方案作为一个自定义 View ,您可以将其复制并粘贴到您的代码库中,并在一些 XML 中使用。

有趣的一点是在 onDraw 重写中,我在这里进行矩阵变换和更新着色器:

class MoveableGradientCircle @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
// Struct for all the data which needs pre-allocating
private data class Circle(
val radius: Float,
val centerX: Float,
val centerY: Float,
val paint: Paint,
val shaderMatrix: Matrix
)
// Pre-allocate the data
private var circle: Circle = Circle(
radius = 10f,
centerX = x,
centerY = y,
paint = Paint().apply {
isAntiAlias = true
style = Paint.Style.FILL_AND_STROKE
shader = RadialGradient(
centerX = 0f,
centerY = 0f,
radius = 10f,
startColor = Color.RED,
edgeColor = Color.GREEN,
tileMode = Shader.TileMode.CLAMP
)
},
shaderMatrix = Matrix()
)

// Setup a touch listener to update the circles x/y positions on user touch location
init {
setOnTouchListener { view, event ->
view.performClick()
when (event.action) {
MotionEvent.ACTION_DOWN -> {
circle = circle.copy(
centerX = event.x,
centerY = event.y
)
invalidate()
true
}
MotionEvent.ACTION_MOVE -> {
circle = circle.copy(
centerX = event.x,
centerY = event.y
)
invalidate()
true
}
MotionEvent.ACTION_UP -> {
circle = circle.copy(
centerX = event.x,
centerY = event.y
)
invalidate()
true
}
else -> false
}
}
}

override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)

// No need to keep re-allocating shader
// Instead, we update the pre-allocated matrix
// In this case, we'll just translate it to the circles current center x,y
// which happens to be the users touch location
circle.shaderMatrix.reset()
circle.shaderMatrix.setTranslate(
circle.centerX,
circle.centerY
)
// Update the matrix on the shader
circle.paint.shader.setLocalMatrix(circle.shaderMatrix)
// Draw the arc with the updated paint
canvas?.drawArc(
circle.centerX - circle.radius,
circle.centerY - circle.radius,
circle.centerX + circle.radius,
circle.centerY + circle.radius,
0f,
360f,
true,
circle.paint
)
}
}

我希望这对您或将来遇到同样问题的其他人有所帮助!

关于Android LinearGradient 预分配和复用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17884768/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com