在Android王国里,有一群名叫View 的小画家。他们每天都在自己的魔法画板上创作,而这块画板就叫 Canvas(画布) 。今天,我们就跟随小画家"Button"的旅程,揭开Canvas的神秘面纱!
🌅 第一章:画布的诞生------Canvas从哪里来?

-
系统皇帝的画布工厂
当App启动时,系统皇帝SurfaceFlinger会:
- 📜 签发一张物理画布(Surface)
- ✉️ 通过Window 使者传递给ViewRootImpl大臣
-
画布分配仪式
java
arduino// 秘密仪式代码(系统层) public final class ViewRootImpl { private void performDraw() { mView.draw(canvas); // 把Canvas交给顶级View } }
- 每次刷新屏幕(VSync信号到来时)
- ViewRootImpl从Surface解锁一块新画布
- 像圣旨一样传递给顶级View:"开始作画吧!"
🖼️ 第二章:画布的秘密------每个View的Canvas独立吗?
小画家Button的困惑:
"我和隔壁TextView的画布是同一块吗?"
🔍 真相揭秘:

-
共享的源头
整个View树共享同一个Canvas对象!
java
scss// 所有View的draw()都收到同一个Canvas void draw(Canvas canvas) { // Button在这里画自己 canvas.drawRect(...); // 接着把画布传给子View for (View child : children) { child.draw(canvas); // 同一个canvas对象! } }
-
作画规则
- 🧙♂️ 魔法坐标轴 :每个View在画布上有专属区域(由
onLayout()
划定) - ✋ 不越界协议 :View只能在自己的矩形框内作画(
canvas.clipRect()
自动约束) - 🎭 绘制顺序:从底层View到顶层View(防止上层被覆盖)
- 🧙♂️ 魔法坐标轴 :每个View在画布上有专属区域(由
🧪 第三章:实验!当Button和TextView同时作画
java
typescript
// 假设Button的绘制代码
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.RED); // 涂满红色背景
}
// TextView的绘制代码
public void onDraw(Canvas canvas) {
canvas.drawText("Hello", 10, 10, paint); // 写文字
}
神奇的现象:
- Button先拿到画布,把自己的区域涂成红色
- 画布传给TextView,它在同一块画布上写字
- 最终效果:红色底 + 白色文字(不会覆盖Button的红色!)
💡 关键魔法 :
Canvas自动执行坐标变换 !
TextView写字时,坐标系已偏移到自己的位置
⚠️ 第四章:危险的"画布污染"事件
某天,淘气的View修改了画布:
java
scss
public void onDraw(Canvas canvas) {
canvas.rotate(30); // 旋转画布30度
super.onDraw(canvas);
}
灾难发生了!
- 后续所有View的绘制都被旋转了30度!
- 因为Canvas状态被污染(共享画布=共享状态)
🛡️ 解决方案:画布状态存档
java
scss
public void onDraw(Canvas canvas) {
int saveCount = canvas.save(); // 存档当前画布状态
canvas.rotate(30);
drawMyContent(canvas);
canvas.restoreToCount(saveCount); // 读档恢复状态
}
📜 画布法则 :
修改画布前必须
save()
,结束后必须restore()
!
🚀 第五章:硬件加速时代的变革
系统皇帝宣布:"现在启用魔法画架(GPU加速) !"
xml
xml
<!-- AndroidManifest.xml -->
<application android:hardwareAccelerated="true">
画布的变化:
特性 | 软件画布(CPU) | 魔法画架(GPU) |
---|---|---|
Canvas本质 | 内存中的Bitmap | OpenGL指令列表 |
独立性 | 真共享 | 虚拟共享(每个View录自己的GL命令) |
绘制效率 | 慢(逐像素计算) | 快(批量提交GPU执行) |
状态污染风险 | 高(直接修改Canvas) | 低(自动隔离绘制命令) |
✨ 魔法画架原理 :
每个View获得一个DisplayList 录音笔(记录绘制命令)
最终由GPU统一执行所有录音笔指令
🌟 终章:Canvas的永恒真理
小画家Button在王国石碑上刻下:
java
markdown
/*
🖌️ Canvas终极奥义:
1. 来源:由SurfaceFlinger赐予,ViewRootImpl分发
2. 共享性:整个View树共享同一块物理画布
3. 安全法则:修改画布状态必用save/restore!
4. 硬件加速:GPU时代每个View有独立"绘制指令集"
*/
当夕阳西下,所有View的绘制命令汇聚成绚丽画面。记住:
你的手指触碰屏幕的那一刻,
就是Canvas魔法之旅的启程之时! ✨