View 的绘制流程
2016-06-08 15:01
477 查看
View的measure 过程由其measure方法完成,measure 方法是一个final类型的方法,子类不能重写。在view的mesure方法中会调用onmeasure 我们只看onMeasure方法就可了。
View源码:
看着很简单。setMeasuredDimension 方法会设置view的宽高测量值,我们只看getDefaultSize 方法即可
逻辑同样是很清晰,mBackground ==null 时候 返回mMinWidth,而mMinWidth 就是android:minWidth属性值,当然如果不进行设置默认minWidth=0。那么mBackground指的是Drawable.getMinimumWidth()
返回的是Drawable的原始宽度,前提是这个Drawable有原始宽度。那么问题来了Drawable什么情况下没有原始宽度?
ShapeDrawable没有原始宽度,而BitmapDrable有原始宽度
在总结一下getSuggestedMinimumWidth逻辑。view没有设置背景怎么返回minWidth (如果minWidth没有设置值默认为0),view设置了背景则返回mBackground 和 minWIdth中最大的值。
那通过上面可以推出来自定义view需要重写onMesure 方法。并且 宽高值设置wrap_content 和 match_parent 是一样的效果
为什么会出现上面情况
设置 wrap_content的模式为AT_MOST:这样view的宽高为specSize等于parentSize ,很显然view的宽高就等于父容器剩余空间的大小。这种和在不居中使用match_parent完全一致如何解决这样问题。也很简单。
具体宽高默认值给多少根据具体需求。
Eg:可以查看其他系统组件是如何处理 默认宽高值。这里就不进行分析
View源码:
protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize( getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); }
看着很简单。setMeasuredDimension 方法会设置view的宽高测量值,我们只看getDefaultSize 方法即可
public static int getDefaultSize(int size, int measureSpec) { int result = size; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) { case MeasureSpec.UNSPECIFIED: //系统内部使用 result = size; break; case MeasureSpec.AT_MOST: //wrap_content case MeasureSpec.EXACTLY: result = specSize; break; } return result; } 可以看出getDefaultSize 方法很简单,我们只看MOST,EXACTLY就可以简单的说getDefaultSize方法返回值就是measureSpec View测量后宽高。 为什么要说测量后,view的最终宽高在onlayout阶段确定的。所以不许加以区分。但是几乎所有情况下view的 onMeasure,onLayout中的值是一样。 至于UNSPECIFIED,一半用于系统内部测量,宽高就为第一个参数的值 getSuggestedMinimumWidth(), getSuggestedMinimumHeight(), 简单分析一个另个方法类似这里就不进行分析 protected int getSuggestedMinimumWidth() { return (mBackground == null) ? mMinWidthmMinWidth : max(mMinWidth, mBackground.getMinimumWidth()); }
逻辑同样是很清晰,mBackground ==null 时候 返回mMinWidth,而mMinWidth 就是android:minWidth属性值,当然如果不进行设置默认minWidth=0。那么mBackground指的是Drawable.getMinimumWidth()
public int getMinimumWidth() { final int intrinsicWidth = getIntrinsicWidth(); return intrinsicWidth > 0 ? intrinsicWidth : 0; }
返回的是Drawable的原始宽度,前提是这个Drawable有原始宽度。那么问题来了Drawable什么情况下没有原始宽度?
ShapeDrawable没有原始宽度,而BitmapDrable有原始宽度
在总结一下getSuggestedMinimumWidth逻辑。view没有设置背景怎么返回minWidth (如果minWidth没有设置值默认为0),view设置了背景则返回mBackground 和 minWIdth中最大的值。
那通过上面可以推出来自定义view需要重写onMesure 方法。并且 宽高值设置wrap_content 和 match_parent 是一样的效果
为什么会出现上面情况
switch (specMode) { case MeasureSpec.UNSPECIFIED: //系统内部使用 result = size; break; case MeasureSpec.AT_MOST: //wrap_content case MeasureSpec.EXACTLY: result = specSize; break; }
设置 wrap_content的模式为AT_MOST:这样view的宽高为specSize等于parentSize ,很显然view的宽高就等于父容器剩余空间的大小。这种和在不居中使用match_parent完全一致如何解决这样问题。也很简单。
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); //如果宽高与 MeasureSpec.AT_MOST 相等。则宽高等于默认宽高 //宽与MeasureSpec.AT_MOST 相等。则宽等于默认宽 //高与MeasureSpec.AT_MOST 相等。则高等于默认高 }
具体宽高默认值给多少根据具体需求。
Eg:可以查看其他系统组件是如何处理 默认宽高值。这里就不进行分析
相关文章推荐
- 使用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