13问问13答全面学习答全面学习Android View绘制绘制
主要为大家详细介绍了Android View绘制,13问13答帮助大家全面学习Android View绘制,感兴趣的小伙伴们
可以参考一下
本文通过13问13答学习Android View绘制,供大家参考,具体内容如下
1.View的绘制流程分几步,从哪开始?哪个过程结束以后能看到的绘制流程分几步,从哪开始?哪个过程结束以后能看到view??
答:从ViewRoot的performTraversals开始,经过measure,layout,draw 三个流程。draw流程结束以后就可以在屏幕上看到
view了。
2.view的测量宽高和实际宽高有区别吗?的测量宽高和实际宽高有区别吗?
答:基本上百分之99的情况下都是可以认为没有区别的。有两种情况,有区别。第一种 就是有的时候会因为某些原因 view会
多次测量,那第一次测量的宽高 肯定和最后实际的宽高 是不一定相等的,但是在这种情况下
最后一次测量的宽高和实际宽高是一致的。此外,实际宽高是在layout流程里确定的,我们可以在layout流程里 将实际宽高写
死 写成硬编码,这样测量的宽高和实际宽高就肯定不一样了,虽然这么做没有意义 而且也不好。
3.view的的measureSpec 由谁决定由谁决定?顶级顶级view呢?呢?
答:由view自己的layoutparams和父容器 一起决定自己的measureSpec。一旦确定了spec,onMeasure中就可以确定view的
宽高了。
顶级view就稍微特殊一点,对于decorView的测量在ViewRootImpl的源码里。
//desire的这2个参数就代表屏幕的宽高,
childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width);
childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
//decorView的measureSpec就是在这里确定的,其实比普通view的measurespec要简单的多
//代码就不分析了 一目了然的东西
private static int getRootMeasureSpec(int windowSize, int rootDimension) {
int measureSpec;
switch (rootDimension) {
case ViewGroup.LayoutParams.MATCH_PARENT:
// Window can't resize. Force root view to be windowSize.
measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY);
break;
case ViewGroup.LayoutParams.WRAP_CONTENT:
// Window can resize. Set max size for root view.
measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST);
break;
default:
// Window wants to be an exact size. Force root view to be that size.
measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY);
break;
}
return measureSpec;
}
4.对于普通对于普通view来说,他的来说,他的measure过程中,与父过程中,与父view有关吗?如果有关,这个父有关吗?如果有关,这个父view也就是也就是viewgroup扮演了什么角色?扮演了什么角色?
答:看源码:
//对于普通view的measure来说 是由这个view的 父view ,也就是viewgroup来触发的。
//也就是下面这个measureChildWithMargins方法
protected void measureChildWithMargins(View child,
int parentWidthMeasureSpec, int widthUsed,
int parentHeightMeasureSpec, int heightUsed) {
//第一步 先取得子view的 layoutParams 参数值
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
//然后开始计算子view的spec的值,注意这里看到 计算的时候除了要用子view的 layoutparams参数以外
//还用到了父view 也就是viewgroup自己的spec的值
final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
+ widthUsed, lp.width);
final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,