Android的View知识
Android View
颜色
ARGB888
A 透明度 0(0x00)透明 255(0xff)不透明
R 红色 0(0x00)无色 255(0xff)红色
G 绿色 0(0x00)无色 255(0xff)绿色
B 蓝色 0(0x00)无色 255(0xff)蓝色
流程
- 构造函数
- 测量大小(onMeasure)
- 确定View的大小(onSizeChanged)
- 确定子View的布局位置(onLayout 自定义ViewGroup中需要)
- 绘制内容(onDraw)
- 对外提供操作方法和监听回调
Paint
画笔介绍
- 创建Paint
Paint mPaint = new Paint()
- 设置属性
//设置画笔的模式
mPaint.setStyle(args);
//设置画笔的颜色
mPaint.setColor(Color.BLUE);
//设置描边宽度
mPaint.setStrokeWidth(20f)
args的取值:
Paint.Style.STROKE 描边
Paint.Style.Fill 填充
Paint.Style.Fill_AND_STROKE 描边回家填充
Canvas
| 操作类型 | 相关API | 备注 |
|---|---|---|
| 绘制颜色 | drawColor, drawRGB, drawARGB | 使用单一颜色填充整个画布 |
| 绘制基本形状 | drawPoint, drawPoints, drawLine, drawLines, drawRect, drawRoundRect, drawOval, drawCircle, drawArc | 依次为 点、线、矩形、圆角矩形、椭圆、圆、圆弧 |
| 绘制图片 | drawBitmap, drawPicture | 绘制位图和图片 |
| 绘制文本 | drawText, drawPosText, drawTextOnPath | 依次为 绘制文字、绘制文字时指定每个文字位置、根据路径绘制文字 |
| 绘制路径 | drawPath | 绘制路径,绘制贝塞尔曲线时也需要用到该函数 |
| 顶点操作 | drawVertices, drawBitmapMesh | 通过对顶点操作可以使图像形变,drawVertices直接对画布作用、 drawBitmapMesh只对绘制的Bitmap作用 |
| 画布剪裁 | clipPath, clipRect | 设置画布的显示区域 |
| 画布快照 | save, restore, saveLayerXxx, restoreToCount, getSaveCount | 依次为 保存当前状态、 回滚到上一次保存的状态、 保存图层状态、 回滚到指定状态、 获取保存次数 |
| 画布变换 | translate, scale, rotate, skew | 依次为 位移、缩放、 旋转、错切 |
| Matrix(矩阵) | getMatrix, setMatrix, concat | 实际上画布的位移,缩放等操作的都是图像矩阵Matrix, 只不过Matrix比较难以理解和使用,故封装了一些常用的方法。 |
Picture
Picture的简介
| 相关方法 | 简介 |
|---|---|
| public int getWidth () | 获取宽度 |
| public int getHeight () | 获取高度 |
| public Canvas beginRecording (int width, int height) | 开始录制 (返回一个Canvas,在Canvas中所有的绘制都会存储在Picture中) |
| public void endRecording () | 结束录制 |
| public void draw (Canvas canvas) | 将Picture中内容绘制到Canvas中 |
| public static Picture createFromStream (InputStream stream) | (已废弃)通过输入流创建一个Picture |
| public void writeToStream (OutputStream stream) | (已废弃)将Picture中内容写出到输出流中 |
Picture的使用
- 使用Picture提供的draw方法绘制
- 使用Canvas提供的drawPicture方法绘制
- 将Picture包装成PictureDrawable,使用PictureDrawable的draw进行绘制
区别: - 使用Picture的draw会对Canvas造成影响而且可操作性比较弱,影响Canvas的状态(Matrix,Clip)
Bitmap
Bitmap获取方式
| 序号 | 获取方式 | 备注 |
|---|---|---|
| 1 | 通过Bitmap创建 | 复制一个已有的Bitmap(新Bitmap状态和原有的一致) 或者 创建一个空白的Bitmap(内容可改变) |
| 2 | 通过BitmapDrawable获取 | 从资源文件 内存卡 网络等地方获取一张图片并转换为内容不可变的Bitmap |
| 3 | 通过BitmapFactory获取 | 从资源文件 内存卡 网络等地方获取一张图片并转换为内容不可变的Bitmap |
BitmapFactory的使用
- 资源文件(drawable/mipmap/raw):
Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(),R.raw.bitmap);
- 资源文件(assets):
Bitmap bitmap=null;
try {
InputStream is = mContext.getAssets().open("bitmap.png");
bitmap = BitmapFactory.decodeStream(is);
is.close();
} catch (IOException e) {
e.printStackTrace();
}
- 内存卡文件:
Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/bitmap.png");
- 网络文件:
// is代表网络下载中获取的字节流
Bitmap bitmap = BitmapFactory.decodeStream(is);
is.close();
绘制Bitmap的常用方法
// 第一种
public void drawBitmap (Bitmap bitmap, Matrix matrix, Paint paint)
// 第二种
public void drawBitmap (Bitmap bitmap, float left, float top, Paint paint)
// 第三种
public void drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint)
public void drawBitmap (Bitmap bitmap, Rect src, RectF dst, Paint paint)
Path常用方法表
| 作用 | 相关方法 | 备注 |
|---|---|---|
| 移动起点 | moveTo | 移动下一次操作的起点位置 |
| 设置终点 | setLastPoint | 重置当前path中最后一个点位置,如果在绘制之前调用,效果和moveTo相同 |
| 连接直线 | lineTo | 添加上一个点到当前点之间的直线到Path |
| 闭合路径 | close | 连接第一个点连接到最后一个点,形成一个闭合区域 |
| 添加内容 | addRect, addRoundRect, addOval, addCircle, addPath, addArc, arcTo 添加(矩形, 圆角矩形, 椭圆, 圆, 路径, 圆弧) 到当前Path (注意addArc和arcTo的区别) | |
| 是否为空 | isEmpty | 判断Path是否为空 |
| 是否为矩形 | isRect | 判断path是否是一个矩形 |
| 替换路径 | set | 用新的路径替换到当前路径所有内容 |
| 偏移路径 | offset | 对当前路径之前的操作进行偏移(不会影响之后的操作) |
| 贝塞尔曲线 | quadTo, cubicTo | 分别为二次和三次贝塞尔曲线的方法 |
| rXxx方法 | rMoveTo, rLineTo, rQuadTo, rCubicTo | 不带r的方法是基于原点的坐标系(偏移量), rXxx方法是基于当前点坐标系(偏移量) |
| 填充模式 | setFillType, getFillType, isInverseFillType, toggleInverseFillType | 设置,获取,判断和切换填充模式 |
| 提示方法 | incReserve | 提示Path还有多少个点等待加入(这个方法貌似会让Path优化存储结构) |
| 布尔操作(API19) | op | 对两个Path进行布尔运算(即取交集、并集等操作) |
| 计算边界 | computeBounds | 计算Path的边界 |
| 重置路径 | reset, rewind | 清除Path中的内容reset不保留内部数据结构,但会保留FillType.rewind会保留内部的数据结构,但不保留FillType |
| 矩阵操作 | transform | 矩阵变换 |
View的Visibility值
- 0 -- VISIBLE 可见
- 4 -- INVISIBLE 不可见但是占用布局空间
- 8 -- GONE 不可见也不占用布局空间
自定义View分类
- 自定义ViewGroup
自定义ViewGroup一般是利用现有的组件根据特定的布局方式来组成新的组件,大多继承自ViewGroup或各种Layout,包含有子View。
- 自定义View
在没有现成的View,需要自己实现的时候,就使用自定义View,一般继承自View,SurfaceView或其他的View,不包含子View。
自定义View主要的函数
1. 构造函数
public void XView(Context context) {}
public void XView(Context context, AttributeSet attrs) {}
public void XView(Context context, AttributeSet attrs, int defStyleAttr) {}
2. 测量函数(onMeasure)
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthsize MeasureSpec.getSize(widthMeasureSpec); //取出宽度的确切数值
int widthmode MeasureSpec.getMode(widthMeasureSpec); //取出宽度的测量模式
int heightsize MeasureSpec.getSize(heightMeasureSpec); //取出高度的确切数值
int heightmode MeasureSpec.getMode(heightMeasureSpec); //取出高度的测量模式
}
测量模式分三种:在int类型的32位二进制位中,31-30这两位表示测量模式,29~0这三十位表示宽和高的实际值
| 模式 | 数值 | 描述 |
|---|---|---|
| UNSPECIFIED | 00 | 默认值,父控件没有给子view任何限制,子View可以设置为任意大小。 |
| EXACTLY | 01 | 表示父控件已经确切的指定了子View的大小。 |
| AT_MOST | 10 | 表示子View具体大小没有尺寸限制,但是存在上限,上限一般为父View大小。 |
注:对View的宽高进行修改了,不要调用 super.onMeasure( widthMeasureSpec, heightMeasureSpec); 要调用 setMeasuredDimension( widthsize, heightsize);
3. 确定View大小(onSizeChanged)
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
4. 确定View布局位置(onLayout)
确定布局的函数是onLayout,它用于确定子View的位置,在自定义ViewGroup中会用到,他调用的是子View的layout函数。
child.layout(l, t, r, b);
ps:getLeft();
getTop();
| 名称 | 说明 | 函数 |
|---|---|---|
| l | View左侧距父View左侧的距离 | getLeft() |
| t | View顶部距父View顶部的距离 | getTop() |
| r | View右侧距父View左侧的距离 | getRight() |
| b | View底部距父View顶部的距离 | getBottom() |
5. 绘制内容(onDraw)
onDraw是实际绘制的部分,也就是我们真正关心的部分,使用的是Canvas绘图
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
6. 对外提供操作方法和监听回调
控制View或监听View某些状态。
7.事件分发
public boolean dispatchTouchEvent(MotionEvent ev){
//默认为false,不消费当前事件
boolean consume=false;
if(onInterceptTouchEvent(ev)){
//调用onTouchEvent(ev)方法,处理事件
consume=onTouchEvent(ev);
}else{
//调用子元素的dispatchTouchEvent(ev)方法,进行事件分发
consume=child.dispatchTouchEvent(ev);
}
}
用来进行事件的分发。View/ViewGroup接收到触控事件最先调起的就是这个方法,然后在这个方法中判断是否处理拦截或者将事件分发给子元素
public boolean onInterceptTouchEvent(MotionEvent ev)
用来进行事件的拦截。ViewGroup中调用(View中没有此方法),在这个方法中判断是将事件交给ViewGroup处理或者将它传递给子元素,一般在这个方法中处理事件冲突。
public boolean onTouchEvent(MotionEvent event)
用来进行事件的处理。最后每个事件都会在这里被处理。

浙公网安备 33010602011771号