搞 Android 开发的兄弟们都知道,想要进阶高级,自定义 View 绝对是一道绕不过去的坎儿。而在自定义 View 的世界里,如果说 Canvas(画布)是我们的画板,那么 Paint(画笔)就是我们手里的那支马良神笔。
今天,咱们就抛开枯燥的官方文档,用大白话给大家盘一盘 Paint 那些最常用的 API、让人头疼的文字对齐计算,以及能玩出各种炫酷花样的 Shader 渲染特效。
提示:在开始阅读前,大家可以先看一眼下面的知识脑图,对今天要讲的内容有个大致的框架。

一、 Paint 画笔初探:那些藏在源码里的秘密
Paint 主要是用来保存绘制几何图形、文本和位图的样式以及颜色信息的。
如果你平时有翻看源码的习惯,点进 Paint 类看一眼,就会发现里面密密麻麻全是一堆 get/set 方法。更有意思的是,真正干活的方法基本都带着 native 关键字。这意味着啥?意味着我们在 Java/Kotlin 层调用的这些 API,本质上就像是个"遥控器",真正的绘制工作是交给了底层的图形渲染引擎去高效完成的。
二、 常用 API 避坑指南
为了方便记忆,我把平时开发中最常用的 API 分成了几个大类:
1. 基础设置(必会款)
setColor/setARGB:选颜色,调透明度,没啥好说的。setAntiAlias(boolean):抗锯齿 。这个强烈建议在初始化画笔时无脑设置为true!不然画出来的圆边缘全是锯齿,非常影响 UI 质感。setStyle(Paint.Style):画笔模式。FILL:实心填充(默认)。STROKE:空心描边。FILL_AND_STROKE:既填充又描边。
2. 描边细节(UI 设计师的强迫症)
当你的画笔设置为 STROKE(描边)时,这几个方法就派上用场了:
setStrokeWidth:线有多粗。setStrokeCap:线条两端的形状(线帽)。比如BUTT(平头)、ROUND(圆头,画圆角进度条必备)、SQUARE(方头,注意它比平头会长出半个线宽)。setStrokeJoin:线条拐角处的形状。MITER(尖角)、BEVEL(平切角)、ROUND(圆角)。
3. 高级滤镜与特效
setShader(Shader):大招来了,设置渲染器,后面咱们单开一章讲。setXfermode:图层混合模式。配合PorterDuff使用,处理两张图的交集、并集,实现刮刮乐效果全靠它。setFilterBitmap:双线性过滤。简单来说,如果你要把一张小图放大画出来,开启它能让图片不那么"马赛克",过渡更平滑。
三、 让人又爱又恨的 FontMetrics(字体度量)
说到用 Paint 画文字,十个 Android 开发者里有九个都在"文字垂直居中"上踩过坑。这是因为 Android 画文字并不是从左上角开始画的,而是基于一条叫 Baseline(基线)的参考线。
这时候,就轮到 FontMetrics 出场了。
为了更直观地理解,大家一定要对照着下面这张图来看:

我们以红色的 Baseline 为坐标轴的 Y=0(注意:在 Android 坐标系中,向下为正,向上为负):
baseline:基线,文字绘制的基石。ascent:字符最高点到基线的"推荐"距离(绿线,通常是负值)。top:字符最高点到基线的"极限"距离(灰线,绝对值一般比 ascent 大一点)。descent:字符最低点到基线的"推荐"距离(黄线,通常是正值,比如字母 g 下面那个弯弯)。bottom:字符最低点到基线的"极限"距离(紫线)。leading:行间距,就是上一行的 descent 到下一行的 ascent 之间的距离。
实战小技巧: 想要计算一行文字的精确高度怎么办?非常简单,套公式: Height=descent−ascent
四、 Shader 渲染器:给 UI 加点特效
如果说前面的 API 是给图形上单色,那 Shader 就是教你怎么给图形穿上花衣服。Shader 有五大派系,配合 TileMode 可以玩出无数花样:
1. 五大渲染器介绍
LinearGradient(线性渲染):指定起点和终点,颜色顺着一条线慢慢过渡。RadialGradient(环形渲染):像水波纹一样,从一个圆心向外围辐射渐变。SweepGradient(扫描渲染):这个最典型,想想雷达扫描图,或者那种五颜六色的圆环进度条,就是它干的。围绕圆心 360 度顺时针渐变。BitmapShader(位图渲染) :划重点! 这是做"圆形头像"的神器。直接把一张图片当成颜料(纹理)画上去,省去了复杂的图层叠加(Xfermode)裁剪。ComposeShader(组合渲染):如果一种特效不够,那就把两个 Shader 绑在一起,通过图层混合模式叠加,效果拉满。
2. TileMode 排版方式
当你要绘制的区域(比如一个大长方形)比你的 Shader 设定的范围还要大时,超出的部分怎么办?这时候就要选 TileMode 填充规则了:
CLAMP:死命拉伸边缘的最后一个像素,强行铺满剩余空间。REPEAT:像贴瓷砖一样,超出部分不断重复原来的图案。MIRROR:也是平铺,但是每次重复都会像照镜子一样反转一下,衔接处会更自然。
掌握了以上这些 Paint 和 Shader 的核心套路,绝大多数的自定义 View 绘制需求你都能拿捏得死死的了。