Android|Android View 笔记

ViewRoot ViewRoot是连接WindowManager和DecorView的纽带,View的measure,layout和draw都是ViewRoot来完成的

  1. 首先通过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; } } }

  1. 在加载到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 绘制装饰
事件分发 经典的一图流

Android|Android View 笔记
文章图片
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 }

    推荐阅读