android的UI绘制流程

setContentView(R.layout.activity_main);入手了解UI的绘制起始过程

activity.java

public void setContentView(@LayoutRes int layoutResID) {        getWindow().setContentView(layoutResID);//一        initWindowDecorActionBar();    }

getWindow()拿到的是Window的实现类PhoneWindow

PhoneWindow源码: com.android.internal.policy   @Override    public void setContentView(int layoutResID) {        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window        // decor, when theme attributes and the like are crystalized. Do not check the feature        // before this happens.        if (mContentParent == null) {            installDecor();// 二        }        ……     }    //这个layoutResID,就是用户在activity中传进来的布局idmLayoutInflater.inflate(layoutResID, mContentParent);//六    }installDecor()方法加载decorView。  private void installDecor() {        if (mDecor == null) {            mDecor = generateDecor();//三 、生成一个DecorView(继承的FrameLayout)            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);            mDecor.setIsRootNamespace(true);            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);            }        }        if (mContentParent == null) {            mContentParent = generateLayout(mDecor);//四、    }   protected ViewGroup generateLayout(DecorView decor) {//五、    View in = mLayoutInflater.inflate(layoutResource, null);        decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));        mContentRoot = (ViewGroup) in;    }

measure、layout、draw的三个执行流程

view.java源码

在view.java的源码中有三个方法:

  • measure:测量,测量自己有多大。如果是ViewGroup的话会同时测量里面子控件的大小
  • layout: 摆放里面的子控件
  • draw: 绘制

看View.java类的源码:

  1. view的requestLayout()方法开始,递归地不断往上找父容器,最终找到DecorView(是WindowPhone的内部类,继承自帧布局)
  2. 执行了DecorView的ViewRootImpl类的performTranversal()方法
  3. performTranversal()方法如下
performTranversal(){     // Ask host how big it wants to be          performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);      performLayout(lp, desiredWindowWidth, desiredWindowHeight);      performDraw();}
  1. performMeasure()方法 ,执行该方法进行测量
  private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");        try {            mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);        } finally {            Trace.traceEnd(Trace.TRACE_TAG_VIEW);        }    }

viewGroup.java 源码

一、measure的过程

如何去合理的测量一颗view树?

如果ViewGroup和View都是直接指定的宽高,我还要测量吗?

正是因为谷歌设计的自适应尺寸机制(比如Match_parent,wrap_content),造成了宽高不确定,所以就需要进程测量measure过程。
measure过程会遍历整颗View树,然后依次测量每一个View的真实的尺寸。

MeaureSpec:测量规格

在xml文件中的width和height的 match_parent和wrap_content 或者具体的值。在代码中具体体现的都是个32位的int值。所以通常拿这个int值得前2位作为测量模式,后面30位当做值.

  • mode:

    • EXACTLY: 精确的。比如给了一个确定的值100dp和Match_parent属于这种。

    • AT_MOST:根据父容器当前的大小,结合你指定的尺寸参考值来考你应该是多大尺寸,需要计算(wrap_content就是属于这种)

    • UNSPECIFIED: 值未指定的意思。根据当前的情况,结合你指定的尺寸参考值来考虑,在不超过父容器给你限定的值的前提下,来测量你的一个恰好的内容尺寸。

    用的比较少,一般见于ScrollView,ListView(大小不确定,同时大小还是变的。会通过多次测量才能真正决定好宽高。)

  • value:宽高的值

经过大量测量以后,最终确定自己的宽高,需要再调用:setMeasuredDimension(w,h)

写自定义控件的时候,我们要去获得自己的宽高来进行一些计算,必须先经过measure,才能获得到宽高—不是getWidth(),而是getMeasuredWidth()
也就是当我们重写onMeasure的时候,我们需要在里面调用child.measure()才能获取child的宽高。

更多相关文章

  1. android在线源码地址
  2. 输入键盘始终停留以及尺寸转换得到默认字体大小
  3. android中进行https连接的方式(源码)
  4. android联系人源码解析
  5. Android UI的加载源码分析
  6. android 项目源码
  7. Android 相机2之常用工具代码(预览方向、预览尺寸、全屏显示、分

随机推荐

  1. Android(安卓)Storage Manager
  2. Android引路蜂地图开发示例:地址反编码
  3. Android(安卓)Studio中AIDL使用方法
  4. Android进程通信之Messenger&AIDL使用详
  5. Android实现BMP和PNG转换为JPEG格式
  6. android百分比布局PercentRelativeLayout
  7. android中修改string.xml中变量
  8. Android(安卓)build system 分析之 envse
  9. java.lang.RuntimeException: Unable to
  10. Android(安卓)Studio 的六种依赖