ViewRoot
ViewRoot是连接WindowManager和DecorView的纽带,View的measure,layout和draw都是ViewRoot来完成的
- 首先通过WindowManager将DecorView添加到Window中,与此同时将ViewRootImpl对象通过setView将DecorView关联起来.
//WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {//...省略部分代码ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {//...省略部分代码root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
// do this last because it fires off messages to start doing things
try {
//将DecorView关联起来
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
- 在加载到Window之前,其ViewRootImpl内部会通过requestLayout方法来布局整个DecorView树,最终调用performTravels,依次执行DecorView的measure、layout、draw三大过程.
private void performTraversals() {
//...省略部分代码
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
//...省略部分代码
performLayout(lp, mWidth, mHeight);
//...省略部分代码
performDraw();
//...省略部分代码
}
Measure specSize: 32位int的高2位
specMode: 其余30位
Mode 三种模式:
EXACTLY: 精确模式
父View对子view有精确的大小,大小就是specSize.
对应于MACTCH_PARENT和具体数值.
AT_MOST:最大模式
父View对子view最大值有要求,大小就是specSize.
对应于WRAP_CONTENT
UNSPECIFIED
layout 如果子View是纯View,那么在onLayout里,什么都不做.
如果是ViewGroup,那么在onLayout里,首先需要遍历调用所有子view的layout方法,让子View完成自我布局,依次递归.
draw方法里流程 drawBackground 绘制背景
onDraw 绘制自己
dispatchDraw 绘制子view
onDrawScrollBars 绘制装饰
事件分发 经典的一图流
文章图片
14186083-93ad82cb9b1ee4f6.png 【Android|Android View 笔记】伪代码表示:
fun dispatchTouchEvent(ev: MotionEvent) {
var consume = false
if(onInterceptTouchEvent(ev)) {
consume= onTouchEvent(ev)
} else {
consume = child.dispatchTouchEvent(ev)
}
return consume
}