参考:https://blog.csdn.net/guolin_blog/article/details/16330267
一、onMeasure()
-
测量视图的大小:从ViewRoot的perform Traversals()方法中开始,在内部调用View的measure()方法
-
measure()方法会接收两个参数
-
widthMeasureSpec
-
heightMeasureSpec
-
这两个参数是父视图计算后传递给子视图的
-
最外层的根视图的两个参数是通过getRootMeasureSpec(desiredWindowWidth, lp.width);方法设置的
-
lp.width和lp.height在创建ViewGroup时就被赋值为match_parent
-
getRootMeasureSpec会返回EXACTLY
-
即根视图总是充满全屏的
-
-
-
-
measure方法是final的,无法在子类重写,其中onMeasure方法是真正测量并设置View大小的地方
-
-
MeasureSpec的值由specSize和specMode共同组成
-
specSize:大小
-
specMode:规格
-
EXACTLY:固定、match_parent
-
AT_MOST:wrap_content
-
UNSPECIFIED:一半不太会用到
-
-
measureSpec是一直从measure()方法中传递过来的,然后调用MeasureSpec.getMode()解析出specMode
-
二、onLayout()
-
给视图进行布局,确认视图的位置,ViewRoot的performTraversals()方法会在measure结束后继续执行,并调用View的layout()方法来执行此过程
-
layout()方法接收上下左右四个参数
-
收线调用setFrame()方法来判断视图的大小是否发生过变化,以确定有没有必要重绘
-
调用onLayout()方法,目的是确认视图的位置
-
-
-
实际上这个操作时ViewGroup中的onLayout()来完成
-
ViewGroup中的onLayout()是一个抽象方法,子类自己去实现
-
-
onLayout()结束后,可以调用getWidth()和getHeight()去获取视图的宽高了
-
getWidth()和getMeasureWidth()区别
-
getMeasureWidth在measure结束后就可以获取到,getWidth要在layout()以后才能获取到
-
getMeasureWidth的值是通过setMeasuredDimension()方法设置的,getWidth是通过视图右边坐标减去左边左边计算出来的
-
三、onDraw()
-
ViewRoot会创建一个Canvas对象,然后调用View的draw()方法来执行具体的绘制工作
-
首先绘制背景
-
此处会得到一个mBGDrawable对象
-
然后根据layout过程确定的视图位置来设置背景的绘制区域
-
然后调用Drawable的draw方法来完成背景的绘制工作
-
-
对视图的内容进行绘制
-
调用了onDraw方法,交给子类去实现
-
-
对当前视图的所有子视图进行绘制
-
view中的dispatchDraw方法也是空方法,ViewGroup的dispatchDraw方法中有具体的绘制代码
-
-
对视图的滚动条进行绘制
-
任何一个视图都有滚动条,只不过一般不显示出来
-
-