Android自定义View绘制颜色异常:初始红色圆圈为何显示为绿色?
嘿,这个问题我之前也踩过坑,是Paint的状态复用特性导致的,我来给你拆解清楚:
问题根源
Paint是一个带状态的对象,你设置的所有属性(比如颜色、笔触样式)都会被持久保存,不会自动重置。而View的onDraw()方法可不是只执行一次——系统会在很多场景下触发重绘(比如屏幕旋转、界面被遮挡后恢复、调用invalidate()等)。
看你的代码流程:
- 第一次
onDraw()执行:- 用初始的红色画第一个圆
- 把
drawPaint改成蓝色,画第二个圆 - 再改成绿色,画第三个圆
- 第二次及之后的
onDraw()执行:- 此时
drawPaint的颜色已经是上一次最后设置的绿色了!所以第一个圆直接用绿色绘制,之后才改成蓝色、绿色,最终就出现了第一个圆是绿色的诡异结果。
- 此时
两种解决办法
办法1:每次重绘前重置Paint的初始状态
在onDraw()开头把drawPaint的颜色改回初始的红色,确保每次重绘都从正确的状态开始:
override fun onDraw(canvas: Canvas?) { drawPaint.color = Color.RED // 重置初始颜色,避免上次重绘的状态残留 canvas?.drawCircle(50f, 50f, 40f, drawPaint) drawPaint.color = Color.BLUE canvas?.drawCircle(50f, 150f, 40f, drawPaint) drawPaint.color = Color.GREEN canvas?.drawCircle(50f, 250f, 40f, drawPaint) }
办法2:为不同颜色创建独立的Paint实例(更推荐)
既然不同圆需要不同的颜色,干脆直接创建多个Paint对象,每个对应一种颜色,彻底避免状态污染的问题。而且可以通过复制已有Paint的属性来简化代码:
class SimpleDrawingView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyle: Int = 0 ) : View(context, attrs, defStyle) { // 基础配置的Paint,作为模板 private val basePaint: Paint = Paint().apply { isAntiAlias = true strokeWidth = 5f style = Paint.Style.STROKE strokeJoin = Paint.Join.ROUND strokeCap = Paint.Cap.ROUND } // 复制基础配置,只修改颜色 private val redPaint = Paint(basePaint).apply { color = Color.RED } private val bluePaint = Paint(basePaint).apply { color = Color.BLUE } private val greenPaint = Paint(basePaint).apply { color = Color.GREEN } override fun onDraw(canvas: Canvas?) { canvas?.drawCircle(50f, 50f, 40f, redPaint) canvas?.drawCircle(50f, 150f, 40f, bluePaint) canvas?.drawCircle(50f, 250f, 40f, greenPaint) } }
这种方式更清晰,尤其当你的Paint有很多复杂配置时,不用每次重复设置,也不用担心重绘时的状态残留问题。
内容的提问来源于stack exchange,提问作者Rarity7-
相关产品推荐
相关产品推荐

