Android自定义控件(二)

一、简介

在准备好自定义View后,就可以对其绘制了,需要我们在重写的onDraw函数中进行绘制。
此时我们就需要画布(Canvas)和画笔(Paint)。

Canvas类包含“绘制”调用。要绘制一些东西,你需要4个基本组件:一个用于容纳像素的位图,一个用于托管绘图调用的Canvas(写入位图),一个绘图基元(例如Rect,Path,text,Bitmap)和一个paint(to描述绘图的颜色和样式)。
这是官网中对Canvas的解释,感觉更像是对绘制的解释。

二、Canvas

构造函数

根据构造函数可知可以创建一个空的画布,或者具有要绘制的指定位图的画布。

Canvas()
Canvas(Bitmap bitmap)

常用函数

如:

  • drawPoint:画点
  • drawLine:画线
  • drawRect:画矩形
  • drawCircle:画圆
  • drawArc:画圆弧
  • drawBitmap:画位图
  • drawText:画文字

drawXXX

这类都以drawXXX的形式函数。并且重载函数特别多,但是很多参数都离不开几个东西。

drawPoint

drawPoint(float x, float y, Paint paint)
对应的坐标点位和Paint,即可完成点的绘制。

drawRect

drawRect(RectF rect, @NonNull Paint paint)
同上,需要的是一个Rect/RectF。两者的区别就是Rect的参数为int、而RectF的参数为float。

drawText

drawText(String text, float x, float y, Paint paint)
在画文字需要注意,我们使用的Paint一定要设置setTextSize()值。

画布的matrix操作

平移

translate(float dx, float dy)
会将画布的坐标原点进行平移,建立新的坐标系。

旋转

rotate(float degrees) rotate (float degrees, float px, float py)
第一个构造函数直接输入旋转的度数,正数是顺时针旋转,负数指逆时针旋转,它的旋转中心点是原点(0,0)
第二个构造函数除了度数以外,还可以指定旋转的中心点坐标(px,py)

缩放

scale(float sx, float sy) scale (float sx, float sy, float px, float py)
第一个构造函数设置了水平缩放的比例,小数为缩小,为整数为放大

三角函数

void skew (float sx, float sy)
float sx:将画布在x方向上倾斜相应的角度,sx倾斜角度的tan值,
float sy:将画布在y轴方向上倾斜相应的角度,sy为倾斜角度的tan值,

裁剪

`
boolean clipRect(Rect rect)

这里的裁剪函数特别多,都是以clipXXX`形式。
裁剪这个区域为新的画布,并进行我们想要的处理

画布的保存与恢复

int save () void restore()
save:把当前的画布的状态进行保存,然后放入特定的栈中
restore:把栈中最顶层的画布状态取出来,并按照这个状态恢复当前的画布,并在这个画布上做画

saveLayer

int saveLayer(RectF bounds, Paint paint, int saveFlags) int saveLayer(float left, float top, float right, float bottom,Paint paint, int saveFlags)
调用saveLayer时,会生成了一个全新的bitmap,这个bitmap的大小就是我们指定的保存区域的大小,新生成的bitmap是全透明的,在调用saveLayer后所有的绘图操作都是在这个bitmap上进行的。在画图完成之后,会把saveLayer所生成的bitmap盖在原来的canvas上面。
RectF:要保存的矩形区域
saveFlags:
| FLAG 名称 | 功能 |
| —————- | ——— |
|ALL_SAVE_FLAG|保存全部内容|
|MATRIX_SAVE_FLAG|只保存matrix操作的画布(只会恢复画布的位置信息,有关画布的大小,是不会被恢复的。另外saveLayer使用需要配合Canvas.HAS_ALPHA_LAYER_SAVE_FLAG,不然新建画布所在区域原来的图像将被清空。)|
|CLIP_SAVE_FLAG|仅保存Canvas的裁剪信息,只恢复Canvas的大小(另外saveLayer使用需要配合Canvas.HAS_ALPHA_LAYER_SAVE_FLAG,不然新建画布所在区域原来的图像将被清空。)|
|HAS_ALPHA_LAYER_SAVE_FLAG|新建的bitmap画布在与上一个画布合成时,不会将上一层画布内容清空,直接盖在上一个画布内容上面(saveLayer专用)|
|FULL_COLOR_LAYER_SAVE_FLAG|则表示新建的bimap画布在与上一个画布合成时,先将上一层画布对应区域清空,然后再盖在上面(saveLayer专用)|
|CLIP_TO_LAYER_SAVE_FLAG|在保存图层前先把当前画布裁剪(与CLIP_SAVE_FLAG共用,则Canvas会恢复)|

saveLayerAlpha

int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) int saveLayerAlpha(float left, float top, float right, float bottom,int alpha, int saveFlags)
多一个alpha参数,用以指定新建画布透明度,取值范围为0-255。

restoreToCount

在调用saveXXX函数是会回调一个int值的ID,因为save会将当前图片压入栈中,因此回调的ID则是当前所在的索引(从0开始)。
而restoreToCount可以指定ID退栈(从1开始)。因此当我们压入一个页面后,将ID返回给restoreToCount后,就会直接将该页面退栈。
github

三、Paint

Paint类包含有关如何绘制几何,文本和位图的样式和颜色信息。

构造函数

Paint()
Paint(int flags)
Paint(Paint paint)

这里只有第二个需要注意,flags参数可以在setFlags单独设置。而flags也有很多,如ANTI_ALIAS_FLAG是绘制时绘制抗锯齿的绘制标记。
| 名称 | 功能 |
| ——- | ——— |
|ANTI_ALIAS_FLAG|绘制时绘制抗锯齿的绘制标记|
|FILTER_BITMAP_FLAG|绘制标志,在缩放的位图上启用双线性采样|
|DITHER_FLAG|在绘制时启用抖动的绘制标记|
|UNDERLINE_TEXT_FLAG|绘制标志,将下划线装饰应用于绘制文本|
|STRIKE_THRU_TEXT_FLAG|绘制标记,将穿透装饰应用于绘制文本|
|FAKE_BOLD_TEXT_FLAG|绘制标志,将合成粗体效果应用于绘制文本|
|LINEAR_TEXT_FLAG|绘制标志,可以实现文本的平滑线性缩放|
|SUBPIXEL_TEXT_FLAG|绘制标志,用于启用子像素定位文本|
|DEV_KERN_TEXT_FLAG|Legacy Paint标志,不再使用|
|LCD_RENDER_TEXT_FLAG|
|EMBEDDED_BITMAP_TEXT_FLAG|绘制标记,用于在绘制文本时使用位图字体|

常用函数

函数名 功能
setColor(int color) 设置画笔颜色颜色
setStrokeWidth(float width) 设置画笔粗细
setTextSkewX(float f) 设置倾斜,负右斜,正为左
setARGB(int a,int r,int g,int b) 设置颜色,一个为透明度
setTextSize(float textSize) 设置绘制文字大小
setFakeBoldText(boolean fakeBoldText) 是否粗体
setTextAlign(Paint.Align align) 设置文字对齐方式,左,中,右
setUnderlineText(boolean underlineText) 设置下划线
setStyle(Style style) 设置画笔样式,填充,描边,FILL_AND_STROKE
setTypeface(Typeface typeface) 设置字样对象,即字体风格,包括粗体,斜体以及衬线体,非衬线体等
函数名 功能
setDither(boolean dither) 设置抖动处理
setAlpha(int a) 设置透明度
setAntiAlias(boolean aa) 是否开启抗锯齿
setFilterBitmap() 是否开启优化位图
setColorFilter(ColorFilter filter) 设置颜色过滤
setMaskFilter(MaskFilter maskfilter) 设置滤镜的效果
setShader(Shader shader) 设置图像渐变效果
setSrokeJoin(Paint.Join join) 设置图像结合方式
setXfermode(Xfermode xfermode) 设置图像重叠效果
setPathEffect(PathEffect effect) 设置路径效果
reset() 恢复默认设置

设置字体

setTypeface(Typeface typeface)设置字体
系统字体给了五种:
| 常数名 | 格式 |
| ——— | —— |
| DEFAULT|默认|
| DEFAULT_BOLD|加粗|
| SANS_SERIF|非西洋字体|
| SERIF|西洋字体|
| MONOSPACE|宽体|

加载自定义字体

Typeface createFromAsset(AssetManager mgr, String path)指定assets资源加载字体
Typeface createFromFile(String path)指定路径加载字体
Typeface createFromFile(File file)指定文件加载字体

create()

也可以通过Typefacecreate(Typeface family, int style)获取字体
这里的style常用常数如下:
| 常数名 | 格式 |
| ——— | —— |
| NORMAL | 默认 |
| BOLD | 粗体 |
| ITALIC | 斜体 |
| BOLD_ITALIC | 粗斜体 |

笔样式

setStyle()
样式如下:
| 常数名 | 功能 |
| ——— | —— |
|Paint.Style.FILL | 实心 |
|Paint.Style.STROKE | 空心 |
|Paint.Style.FILL_AND_STROKE | 实心加描边 |

FontMetrics

Paint.FontMetrics中标注了Android font的字体排版。
在文字中首先会建立一个内部直角坐标系,同屏幕坐标一样,向下向右为正。x轴与BaseLine线重合。
github

BaseLine:基准线BaseLine
Ascent:字符最高点到baseline的推荐距离
Descent:字符最低点到baseline的推荐距离
Top:字符最高点到baseline的最大距离
Botttom:字符最低点到baseline的最大距离
Leading:两行之间, 上一行的bottom和下一行的top的间距, 然而这个值总是0, 可以忽略

字符的宽度可以通过measureText函数获取,而高度可以通过|Top|+|Bottom|来获取。