图形绘制四个阶段
一. Canvas常用图形绘制方法和Paint基本API
二. Paint详解
-
颜色
-
效果
-
drawText()相关
-
初始化
三. Canvas对绘制的辅助–范围裁切和几何变换
四. 图形绘制顺序的控制
一、 绘制基础
Canvas
图形绘制API:
drawColor
:绘制背景drawLine
:绘制直线drawPoint
:绘制点drawPath
绘制路径drawRect
:绘制矩形drawOval
:绘制弧形
Path
addXXX
:直接添加一个固定形状图形的路径moveTo
:移动画笔位置但是不留下痕迹lineTo
:直线arcTo(Rect rect,float startAngle,float sweepAngel)
:曲线close()
自动连接起点与终点
注意点
不是所有的Path都需要封闭图形,
但Style为FILL
、FILL_AND_STROKE
时会自动的封闭图形,所以这时需要将Style设置为STROKE
Paint(用来设置图形绘制中的画笔属性)
-
setColor()
:设置颜色 -
setStyle()
:设置填充样式- Paint.Style.FILL
- Paint.Style.STROKE
- Paint.Style.FILL_AND_STROKE
-
setStrokeWidth()
:设置描边的宽度
Region(区域)
作用:region的主要作用不是去绘制图片,而是用来处理图形相交时的处理逻辑
-
如何获取Region
set(Rect rect)
:设置一块矩形区域set(int left,int top,int right,int bottom)
:通过左上与右下坐标确定一个矩形区域setPath(Path path,Region region)
:通过Path与另外一个Region的交集获取一个新的区域,不规则区域的获取一般都是通过这个方法
-
图形相交的几种处理方式(
op方法
)UNION
:两个区域的并集INTERSECT
:两个区域的交集XOR
:两个区域的异并集(交集外的区域)DIFFERENCE
:区域1跟区域2不同的地方REVERSE_DIFFERENCE
:区域2跟区域1不同的地方REPLACE
:最终区域为区域2
二、 Paint详解
1. 颜色
Canvas绘制三层颜色的处理
基本颜色设置的三种方式:
- Canvas的drawColor(),这里的颜色控制的是画布的颜色
- Bitmap的颜色直接由自身的像素控制
- 图形与文本的颜色(这两种的颜色就是Paint来进行控制了,后面关于颜色的API我们也是针对的Paint来说的)
Paint设置颜色两种类别
1. 直接设置颜色
setColor(int color)
setARGB(int a,int r,int g,int b)
2. Shader(着色器)
着色器的作用是用来给空白图形进行着色用的
几种常用的Shader
- LinearGradient 线性渐变
- RadialGradient 辐射渐变
- SweepGradient 扫描渐变
- BitmapShader 位图着色器
- BitmapShader需要注意的是Bitmap显示的位置与无关,
默认会自动的从控件的左上角开始平铺,如果想要移动显示的位置,可以通过给BitmapShader
设置一个Matrix并进行位移来控制
- BitmapShader需要注意的是Bitmap显示的位置与无关,
- ComposeShader 混合着色器
/** Create a new compose shader, given shaders A, B, and a combining mode. When the mode is applied, it will be given the result from shader A as its "dst", and the result from shader B as its "src". @param shaderA The colors from this shader are seen as the "dst" by the mode @param shaderB The colors from this shader are seen as the "src" by the mode @param mode The mode that combines the colors from the two shaders. If mode is null, then SRC_OVER is assumed. */ public ComposeShader(Shader shaderA, Shader shaderB, Xfermode mode) {}
- 通过构造函数和注释我们可以知道
shaderA
代表的是dst
,shaderB
代表的是src
,所以当我们选择Xfermode
时要注意
- 通过构造函数和注释我们可以知道
几种TileMode
- TileMode.CLAMP:用边缘色彩来填充多余空间
- TileMode.REPEAT:重复原图来填充多余空间
- TileMode.MIRROR:重复使用镜像模式来填充多余空间
ColorFilter
setColorFilter(ColorFilter colorFilter)
- LightingColorFilter
- 构造函数
LightingColorFilter(int mul, int add)
,颜色的过滤或者加强减弱都可以通过这个公式
R' = R * mul.R / 0xff + add.R G' = G * mul.G / 0xff + add.G B' = B * mul.B / 0xff + add.B
- 构造函数
- ColorMatrixColorFilter
可以看到通过传入一个public ColorMatrixColorFilter(ColorMatrix matrix)
ColorMatrix
来进行颜色控制,同时ColorMatrix
也提供了很多常见的API进行色彩控制 - PorterDuffColorFilter
Xfermode
setXfermode(Xfermode xfermode)
- PorterDuffXfermode
目前只有这一种Xfermode
- 还需要注意的是,在使用Xdermode的使用我们需要在绘制前
saveLayer()
,并在绘制完成后调用restore()
开启离屏缓冲
PorterDuff.Mode
- Alpha混合
- 混合(Blending)
2. 效果
-
setAntiAlias(boolean aa):是否开启抗锯齿
-
setStyle(Paint.Style style):设置画笔样式
- Paint.Style.FILL 填充内部
- Paint.Style.FILL_AND_STROKE 填充内部与描边
- Paint.Style.STROKE 仅描边
Path相关
- setStrokeCap(Paint.Cap cap):设置线段线帽
- Cap.ROUND(圆形线帽)
- Cap.SQUARE(方形线帽)
- Cap.BUTT(无线帽)
设置线帽样式(实际效果有线帽的话会比原本的长度多出一小段来)
- setStrokeJoin(Paint.Join join):设置线段拐角
- Join.MITER(结合处为锐角)
- Join.ROUND(结合处为圆角)
- Join.BEVEL(结合处为平角)
setStrokeMiter(float miter):用来设置拐角延长线的最大值
图形的轮廓效果(Canvas所有设置的图形都有效)
setPathEffect(PathEffect effect)
- CornerPathEffect 圆角效果
- DiscretePathEffect 线条随机偏移
- DashPathEffect 虚线效果
- PathDashPathEffect 用一个Path形成的图形做虚线效果
- SumPathEffect 按照多种方式的轮廓分别进行处理并绘制
- ComposePathEffect 按照顺序处理多种轮廓效果,按照最终处理完的效果进行显示
阴影效果
setShadowLayer(float radius, float dx, float dy, int shadowColor)
radius 是阴影的模糊范围; dx dy 是阴影的偏移量; shadowColor 是阴影的颜色。
设置在绘制层上方的附加效果
setMaskFilter(MaskFilter maskfilter)
- BlurMaskFilter 模糊效果
- NORMAL:内部外部都模糊
- SOLID:内部正常绘制,外部模糊
- INNERL:内部模糊,外部正常
- OUTER:内部不绘制,外部模糊
- EmbossMaskFilter 浮雕效果
色彩优化
-
setDither(boolean dither):图像防抖
-
setFilterBitmap(boolean filter):设置是否使用双线性过滤来绘制 Bitmap
3. 文字相关
Canvas绘制文字的方式
- drawText(String text, float x, float y, Paint paint)
- drawTextOnPath()
drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint)
hOffset:水平偏移量
vOffset:数值偏移量
- StaticLayout
绘制一般的文本,但是需要能够识别换行等符号时,可以使用StaticLayout
StaticLayout(CharSequence source, TextPaint paint, int width, Layout.Alignment align, float spacingmult, float spacingadd, boolean includepad)
width 是文字区域的宽度,文字到达这个宽度后就会自动换行;
align 是文字的对齐方向;
spacingmult 是行间距的倍数,通常情况下填 1 就好;
spacingadd 是行间距的额外增加值,通常情况下填 0 就好;
includepad 是指是否在文字上下添加额外的空间,来避免某些过高的字符的绘制出现越界。
FontMetrics
baseline:基准线,用来确定文本绘制的位置
ascent:系统推荐的单个字符最高高度
descent:系统推荐的单个字符最低高度
top:可绘制的最高高度
bottom:可绘制的最低高度
常用使用用法
FontMetrics metrics = paint.getFontMetrics();
注意点
需要注意的是FontMetric获得的ascent
、descent
并不是真实的对应的线,只是用来帮助我们得到对应线段的,想要获取我们需要通过baseline
的y坐标进行加减后获取。
Paint对文本绘制的辅助
- 设置显示效果类
- setTextSize(float textSize) 字体大小
- setTypeface(Typeface typeface) 设置字体
- setFakeBoldText(boolean fakeBoldText) 设置伪粗体
- setStrikeThruText(boolean strikeThruText) 设置删除线
- setUnderlineText(boolean underlineText) 设置下划线
- setTextSkewX(float skewX) 设置文本倾斜角度
- setTextScaleX(float scaleX) 设置字体横向放缩
- setLetterSpacing(float letterSpacing) 设置字符间距
- setTextAlign(Paint.Align align) 设置文本对齐方式
- setTextLocale(Locale locale) / setTextLocales(LocaleList locales) 根据Local显示文本
- 测量文字尺寸类
- getFontSpacing() 获取行间距
- getTextBounds(String text, int start, int end, Rect bounds) 获取字符占用的矩形
- float measureText(String text) 获取显示字符共占用的宽度,
- 实际场景的用法
三段文本通过measureText获取每段占用的宽度,便能够将三行文本在一行相邻显示
- 实际场景的用法
- getTextWidths(String text, float[] widths) 获取每个字符占用的宽度
- int breakText(String text, boolean measureForwards, float maxWidth, float[] measuredWidth) 根据给定的宽度上线获取文本实际显示的宽度
4. 初始化
- rest() 重置属性
- set(Paint src) 从另外一个Paint中将所有设置的属性赋值过来
- setFlags() 相当于setXX()
三、Canvas对绘制的辅助–范围裁切和几何变换
- 范围裁切
- clipRect()
- clipPath()
- 几何变化
-
常见的几何变化API
- Canvas.translate() 平移
- Canvas.rotate() 旋转
- Canvas.scale() 尺寸缩放
- skew() 斜切
-
使用Matrix来做变换
-
使用Camera来做三位变换
四、图形绘制顺序的控制
总结
参考
《Android自定义控件开发入门与实战》