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 View 笔记_第1张图片
14186083-93ad82cb9b1ee4f6.png

伪代码表示:

fun dispatchTouchEvent(ev: MotionEvent) {
  var consume = false
  if(onInterceptTouchEvent(ev)) {
       consume  = onTouchEvent(ev)
  } else {
     consume = child.dispatchTouchEvent(ev)
  }
  return consume 
}

你可能感兴趣的:(Android View 笔记)