涉及知识
绘制过程涉及到主要方法
类别 | API | 描述 |
---|---|---|
布局 | onMeasure | 测量View与Child View的大小 |
onLayout | 确定Child View的位置 | |
onSizeChanged | 确定View的大小 | |
绘制 | onDraw | 实际绘制View的内容 |
事件处理 | onTouchEvent | 处理屏幕触摸事件 |
重绘 | invalidate | 调用onDraw方法,重绘View中变化的部分 |
Canvas涉及到主要方法
类别 | API | 描述 |
---|---|---|
绘制图形 | drawPoint、drawPoints、drawLine、drawLines、drawRect、drawRoundRect、drawOval、drawCircle、drawArc | 依次为绘制点、直线、矩形、圆角矩形、椭圆、圆、散形 |
绘制文本 | drawText、drawPosText、drawTextOnPath | 依次为绘制文字、指定每个字符位置绘制文字、根据路径绘制文字 |
画布变换 | translate、scale、rotate、skew | 依次为平移、缩放、旋转、倾斜(错切) |
画布裁剪 | clipPath、clipRect、clipRegion | 依次为按路径、按矩形、按区域或对画布进行裁剪 |
Paint涉及到主要方法
类别 | API | 描述 |
---|---|---|
颜色 | setColor、setARGB、setAlpha | 依次为设置画笔颜色、透明度 |
类型 | setStyle | 填充(FILL),描边(STROKE),填充加描边(FLIL_STROKE) |
抗锯齿 | setAntiAlias | 画笔是否抗锯齿 |
字体大小 | setTextSize | 设置字体到大小 |
字体测量 | getFontMetrics()、getFontMetricsInt() | 返回字体测量,返回依次为float、int |
文字宽度 | measureText | 返回文字到宽度 |
文字对齐方式 | setTextAlign | 左对齐(LEFT)、居中对齐(CENTER)、右对齐(RIGHT) |
宽度 | setStrokeWidth | 设置画笔宽度 |
笔锋 | setStrokeCap | 默认(BUTT),半圆形(ROUND),方形(SQUARE) |
(注:因API较多,只列出常用到方法,想了解更多,请查看官方文档)
一、坐标系
1、屏幕坐标系
屏幕坐标系以手机屏幕到左上角为坐标原点,过原点的水平直线为X轴,向右为正方向;过原点的垂线为Y轴,向下为正方向;
2、View坐标系
View坐标系以父视图到左上角为坐标原点,过原点的水平直线为X轴,向右为正方向;过原点的垂线为Y轴,向下为正方向
View内部拥有四个函数,用于获取View到位置
getTop(); //View的顶边到其Parent View的顶边的距离,即View的顶边与View坐标系的X轴之间的距离
getLeft(); //View的左边到其Parent View的左边的距离,即View的左边与View坐标系的Y轴之间的距离
getBottom(); //View的底边到其Parent View的顶边的距离,即View的底边与View坐标系的X轴之间的距离
getRight(); //View的右边到其Parent View的左边的距离,即View的右边与View坐标系的Y轴之间的距离
如图所示
二、绘制过程
1、自定义属性
参考Android 自定义View二(深入了解自定义属性attrs.xml)
2、onMeasure
参考Android 自定义View 一(初体验onDraw(),自定义属性,onMeasue()方法,测量换行)
3、onLayout
用于确定View以及其子View的布局位置,在ViewGroup中,当位置被确定后,它在onLayout中会遍历所有到child并调用其layout,然后layout内部会再调用child到onLayout确定child view到布局位置
layout放法如下
public void layout(int l, int t, int r, int b) {
····
int oldL = mLeft;
int oldT = mTop;
int oldB = mBottom;
int oldR = mRight;
····
for (int i = 0; i < numListeners; ++i) {
listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
}
}
}
·····
}
mLeft,mTop,mBottom,mRight四个参数分别通过getLeft(),getTop(),getBottom(),getRight(),四个函数获得,这一组old值会在位置改变时,调用onLayoutChanges时使用到
4、onSizeChanged
如其名,在View大小改变是调用此函数,用于确定View的大小。至于View大小为什么会改变,因为View的大小不仅由本身确定,同事还受父View到影响
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
这里到w、h就是确定后到高宽值,如果查看View中的onLayoutChange也会看到类似的情况,拥有l, t, r, b, oldL, oldT, oldR, oldB,新旧两组参数
5、onDraw
onDraw是View的绘制部分,给了我们一张空白的画布,使用Canvas进行绘制。也是后面几篇文章所要分享的内容。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
6、onTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
当返回true时,说明该View消耗了触摸事件,后续到触摸事件由它来进行处理。返回false时,说明该View对触摸事件不感兴趣,事件继续传递下去。触屏事件类型被封装在MotionEvent中,MotionEvent提供了很多类型事件,主要关系以下几种类型:
事件类型 | 描述 |
---|---|
ACTION_DOWN | 手指按下 |
ACTION_MOVE | 手指移动 |
ACTION_UP | 手指抬起 |
在MotionEvent中有两组可以获得触摸位置到函数
event.getX(); //触摸点相对于View坐标系的X坐标
event.getY(); //触摸点相对于View坐标系的Y坐标
event.getRawX(); //触摸点相对于屏幕坐标系的X坐标
event.getRawY(); //触摸点相对于屏幕坐标系的Y坐标
如图所示:
onWindowFocusChanged运行于onMeasure与onLayout之后,可以获取到正确的width、height、top、left等属性值。