Android群英传---View、ViewGroup的测量和绘制
2016-08-17 11:13
453 查看
View的测量
系统通过onMeasure()
对View进行测量
1.系统提供MeasureSpec
类帮助测量View
MeasureSpec是32bit的int值,期中
高2bit为测量的模式,
低30位为测量的大小。用于提高效率
测量的模式如下:
1. ++EXACTLY++
精确值模式:
控件属性
width or height设置为具体数值,如
100dp,或者指定为
match_parent属性,就是该模式。
2. ++AT_MOST++
最大值模式:
控件属性
width or height设置为
wrap_content。此时控件的尺寸不超过父控件允许的最大尺寸即可。
3. ++UNSPECIFIED++
不指定大小的测量模式,View想多大就多大,通常情况下载绘制自定义View时才会使用。
View类默认的
onMeasure()方法只支持
EXACTLY,。
自定义控件想使用
wrap_content就必须重写
onMeasure()来指定
wrap_content时的大小。
*
2. View测量实例
onMeasure()如下@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); }
可以发现,本质上系统最终会调用
setMeasuredDimension(int measuredWidth, int measuredHeight),将测量之后的宽高值设置进去。所以重写
onMeasure()最终是将测量后的宽高值设置给该方法。
因此重写onMeasure()方法如下
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); }
其中
measureWidthor
measureHeight用来测量高度和宽度,代码如下:
//测量宽度 private int measureWidth(int widthMeasureSpec){ //提取出模式以及尺寸 int specMode = MeasureSpec.getMode(widthMeasureSpec); int specSize = MeasureSpec.getSize(widthMeasureSpec); int alone = 0; //精确值模式: 例如200dp or match_parent if(specMode == MeasureSpec.EXACTLY){ alone = specSize; }else{ alone = 200; //????? //最大值模式: wrap_parent if(specMode == MeasureSpec.AT_MOST){ alone = Math.min(alone, specSize); } } return alone; }
//测量高度 private int measureHeight(int heightMeasureSpec){ //提取出模式以及尺寸 int specMode = MeasureSpec.getMode(heightMeasureSpec); int specSize = MeasureSpec.getSize(heightMeasureSpec); int result = 0; //精确值模式: 例如200dp or match_parent if(specMode == MeasureSpec.EXACTLY){ result = specSize; }else{ result = 200; //????? //最大值模式: wrap_parent if(specMode == MeasureSpec.AT_MOST){ result = Math.min(result, specSize); } } return result; }
其中
result = 200;表示在
wrap_content属性的时候获得默认的
200px作为长度
View的绘制
通常通过继承View并且重写它的onDraw()方法来完成绘图。
onDraw()中有一个参数,就是
Canvas canvas对象。使用这个
Canvas对象就可以进行绘图了,其他对象需要用代码创建。
Canvas canvas = new Canvas(bitmap);
为什么要传入bitmap?
不传入bitmap也不会报错,但是不要这么做。bitmap是用来存储所有绘制在
Canvas上的像素信息。之后所有的
Canvas.drawXXX都在该bitmap上。
Bitmap bitmap1 = Bitmap.createBitmap(new int[]{R.color.colorAccent, R.color.colorPrimary}, 200, 100, Bitmap.Config.RGB_565); canvas.drawBitmap(bitmap1, 0,0,null);
ViewGroup的测量
ViewGroup用于管理子View,在控制显示大小时,如果ViewGroup设置为wrap_content时,就需要遍历所有子View来确定大小遍历子View就是调用其onMeasure方法进行测量。View摆放位置就是调用ViewGroup的layout方法,其内部遍历子View的layout方法来指定具体位置。
自定义ViewGroup
通常重写onLayout()控制子
View的显示位置。
如果支持
wrap_content,必须重写
onMeasure()
ViewGroup一般不需要绘制
设置ViewGroup背景颜色的时候,调用onDraw()方法
ViewGroup会调用
dispatchDraw()方法来绘制子View,其通过遍历子View,并且调用其绘制方法。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories