
本文详解如何在继承自 View 的自定义绘图组件(如网格线)中,通过外部调用正确刷新颜色——关键在于统一颜色传参方式、确保 invalidate() 触发重绘,并避免硬编码颜色映射逻辑。
本文详解如何在继承自 `view` 的自定义绘图组件(如网格线)中,通过外部调用正确刷新颜色——关键在于统一颜色传参方式、确保 `invalidate()` 触发重绘,并避免硬编码颜色映射逻辑。
在 Android 开发中,当使用自定义 View(如 DrawGrid)进行动态绘图时,常遇到“颜色不更新”的问题:尽管调用了 invalidate(),界面却仍显示旧颜色。根本原因往往并非重绘机制失效,而是颜色参数传递与处理逻辑存在设计缺陷。
? 问题根源分析
观察原始代码,setCurrentColor(int color) 方法将传入的整型参数当作索引(0/1/2),再映射为 Color.WHITE/RED/BLUE:
public void setCurrentColor(int color) {
switch(color){
case 0: currentColor = Color.WHITE; break;
case 1: currentColor = Color.RED; break;
case 2: currentColor = Color.BLUE; break;
}
paint.setColor(currentColor);
invalidate();
}
但 ColorFragment 中实际调用的是:
drawGrid.setCurrentColor(Color.RED); // 传入的是颜色值(如 -65536),不是索引!
Color.RED 的值是 -65536,远超 case 0/1/2 范围,导致 currentColor 和 paint 均未更新,invalidate() 虽执行,但 onDraw() 使用的仍是旧颜色。
✅ 正确解决方案:直接传递颜色值
修改 DrawGrid 的 setCurrentColor 方法,接受标准 @ColorInt int 参数(即 ARGB 整型值),移除冗余 switch 映射:
public void setCurrentColor(@ColorInt int color) {
this.currentColor = color;
paint.setColor(color);
invalidate(); // 强制触发 onDraw()
Log.d("DrawGrid", "Color updated to: " + color);
}
同时,确保 Paint 对象在构造时已初始化,并在整个生命周期内复用(当前代码已满足)。
? Fragment 中的调用需同步修正
在 ColorFragment.onCreateView() 中,按钮点击应直接传入颜色常量(而非索引):
red.setOnClickListener(v -> {
drawGrid.setCurrentColor(ContextCompat.getColor(getContext(), R.color.red)); // 推荐:从资源取色
// 或直接使用:drawGrid.setCurrentColor(Color.RED);
requireActivity().getSupportFragmentManager()
.beginTransaction()
.hide(ColorFragment.this)
.commit();
});
blue.setOnClickListener(v -> {
drawGrid.setCurrentColor(ContextCompat.getColor(getContext(), R.color.blue));
requireActivity().getSupportFragmentManager()
.beginTransaction()
.hide(ColorFragment.this)
.commit();
});
? 最佳实践建议:
- 使用 ContextCompat.getColor() 代替硬编码 Color.RED,兼容深色模式与主题变更;
- 避免在 onCreateView() 中重复创建 DrawGrid 实例(当前代码每次 inflate 都新建),应确保全局唯一实例或通过 FragmentManager 共享引用;
- 若 DrawGrid 作为独立 View 添加到布局,建议在 XML 中声明并 findViewById,而非代码动态 add/remove —— 更利于生命周期管理。
✅ 验证效果
修改后,点击按钮将立即触发:
- paint.setColor() 更新画笔颜色;
- invalidate() 发起异步重绘请求;
- onDraw() 被调用,使用新颜色绘制网格线。
Log 输出 "currentColor is now1 -65536" 等值,证明颜色已成功写入。
? 总结
- ❌ 错误做法:用整数索引间接映射颜色,却向方法传入真实颜色值;
- ✅ 正确做法:方法签名直接受 @ColorInt int,由调用方决定颜色来源(资源、常量或计算值);
- ⚠️ 关键保障:invalidate() 必须在 paint.setColor() 后调用,且 Paint 对象不可在 onDraw() 内重建(否则设置失效);
- ?️ 健壮性提升:添加 @ColorInt 注解可借助 Android Lint 检测非法颜色值,预防运行时错误。
遵循此模式,即可稳定实现自定义 View 的实时颜色动态切换。











