Android View的绘制过程

作者: 小智pikapika | 来源:发表于2018-11-18 23:27 被阅读11次

一切的起源

之前有分析过Activity的启动过程,view的绘制起源其实也是包含在其中的,老规矩,先上图:


view的绘制起源

从图中可知,View的绘制起点是在Activity的创建过程中(onResume之前)触发的,由ViewRootImpl承担View的绘制过程,主要分为三个部分:measure(测量)、layout(布局)、draw(绘制)。

measure(测量)过程

其实View的绘制过程和事件传递过程都是类似的,从最底层的DecorView开始,一层层向上冒泡传递,如图所示:

绘制过程
View的measure过程算是绘制过程中最复杂的一部分了,相比于layout、draw只需要拿到测量后的尺寸直接应用即可,measure过程一开始并不知道ViewGroup的最终大小,需要遍历测量所有子view的尺寸,再进行自身的测量,如果有问题可能还需进行再次测量才能得到最终的尺寸,一次绘制过程可能需要多次measure才能完成,所以在自定义view时,最好不要在measure过程去获取view的最终尺寸,在layout之后获取才比较可靠。
measure的尺寸信息使用MeasureSpec来保存,包含mode、size两部分的信息,关于mode有三种模式:
MeasureSpec.UNSPECIFIED:不限尺寸,一般只有系统中的view才能用到
MeasureSpec.AT_MOST:指定最大可用大小,对应于wrap_content
MeasureSpec.EXACLITY:固定大小,对应于match_parent和指定具体宽高
自定义在支持wrap_content时,需要注意复写onMeasure方法,原代码wrap_content会直接当作match_parent处理:
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
    }
    public static int getDefaultSize(int size, int measureSpec) {
        int result = size;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        switch (specMode) {
        case MeasureSpec.UNSPECIFIED:
            result = size;
            break;
        case MeasureSpec.AT_MOST: //对应的wrap_content直接取specSize,相当于match_parent
        case MeasureSpec.EXACTLY:
            result = specSize;
            break;
        }
        return result;
    }

layout和draw过程

layout过程很简单,只需要遍历子view根据规则排列即可。draw过程我们最熟悉的应该是onDraw方法,大部分情况下自定义只需要复写该方法即可,但在对于某些特殊现实效果时就需要注意各个draw方法之间的前后顺序了,后面调用的方法绘制的内容总是会覆盖在前面。

AdjustLayout自动换行布局

这边写了一个自动换行的AdjustLayout自定义view,大家有兴趣可以参考手动去重写绘制过程,相信会对整个绘制流程有更深刻的印象。github地址:AdjustLayout

思考题

文章最初分析了view的绘制起源,介于Activity的onCreate和onResume之间,请大家思考下在onResume中能否获取到view的measuredWidth?这个思考题主要涉及到ViewRootImpl.performTraversal的调用方式和Android的消息机制,类似的问题可以换成在onCreate方法中调用View.post(),是post中的方法先执行还是onResume先执行到,有兴趣的童鞋可以尝试下。(其实这个问题再深入挖掘可以关联到ipc的执行机制,是否会阻塞调用线程呢?)

相关文章

  • Android-View的绘制

    View的绘制过程android程序启动--->Activity加载--->View的绘制 1、前期调用 2、调用...

  • android view draw 矩形、文字、路径

    android view 绘制图形 android view 绘制文本 android view 绘制路径

  • 高级UI

    一、Android 布局添加流程 二、View的绘制流程 1、view绘制流程 2、具体3大绘制过程 1.测量过程...

  • Android-View的测量

    Android View的测量 在绘制View之前,要对整个View进行测量,这个过程就在onMeasure()方...

  • Android View绘制过程

    Activity的布局文件是如何被加载的呢? 1)setContentView(R.layout.main) 通过...

  • Android View的绘制过程

    一切的起源 之前有分析过Activity的启动过程,view的绘制起源其实也是包含在其中的,老规矩,先上图: 从图...

  • Android View的绘制过程

    直接了当的来说,Android系统中View的绘制需要经历三个主要过程: onMeasure()、onLayou...

  • Android View的绘制过程

    View的绘制流程 view的绘制流程是从ViewRoot的performTraversals方法开始的,它经过m...

  • Android 自定义 View

    经过前面几篇文章 View 基础 View 的测量过程 View 的布局和绘制 Android 滑动原理与方式 A...

  • Android View 的绘制流程 04 - performD

    Android View 的绘制流程 - 开篇 MeasureSpecAndroid View 的绘制流程 01 ...

网友评论

    本文标题:Android View的绘制过程

    本文链接:https://www.haomeiwen.com/subject/nghwfqtx.html