美文网首页
View绘制流程

View绘制流程

作者: 三季人 | 来源:发表于2018-08-20 17:05 被阅读14次

    先说说我们平时看见的手机屏幕都包含哪些试图吧
    [图片上传失败...(image-3976a5-1534755895421)]

    Activity界面中的有一个成员window,它的实例化对象是PhoneWindow。
    这里简单说明下这些类:

    - window是一个抽象接口
    - PhoneWindow是window的实例对象
        - 内部包含了一个DecorView,decorView是所有应用窗口(Activity界面)的根布局
        - decorView是PhoneWindow的内部类,本质上是一个FrameLayout
        - decorView中只包含了一个LinearLayout(垂直的)
        - 垂直的linearLayout只包含了两个view,一个是titleBar,一个是id为content的FramLayout
        - 我们setContentView布局实际上就算添加到了content 的FramLayout中了
    

    整体如下图
    [图片上传失败...(image-916c1f-1534755895421)]

    视图的绘制流程

    每一个视图的绘制过程都必须经过三个步骤:onMeasure()、onLayout()、onDraw()

    onMeasure()

    试图的measure测量实际是,从顶层父类view向子view递归调用mesure(里面又调用onMeasure()方法)
    的过程

    MeasureSpec(View的内部类)测量规格为int型,值由高2位规格模式specMode和低30位具体尺寸specSize组成。其中specMode只有三种值:

    MeasureSpec.EXACTLY //确定模式,父View希望子View的大小是确定的,由specSize决定;
    MeasureSpec.AT_MOST //最多模式,父View希望子View的大小最多是specSize指定的值;
    MeasureSpec.UNSPECIFIED //未指定模式,父View完全依据子View的设计值来决定;

    view 的measure 是final,不能重载,所以view 只能调用onMeasure()
    view 的getMeasuredWidth()和getMeasuredHeight()来获取view的宽高,但是只能在onMeasure()之后,才能正常的获取到

    layout()

    和mesure类似,layout也是从顶层父类向子类递归调用了layout()方法,通过上一步onMeasure()获取子类的大小,将子类放在合适的位置

    View.layout方法可被重载,ViewGroup.layout为final的不可重载,ViewGroup.onLayout为abstract的,子类必须重载实现自己的位置逻辑。

    measure操作完成后得到的是对每个View经测量过的measuredWidth和measuredHeight,layout操作完成之后得到的是对每个View进行位置分配后的mLeft、mTop、mRight、mBottom,这些值都是相对于父View来说的。

    凡是layout_XXX的布局属性基本都针对的是包含子View的ViewGroup的,当对一个没有父容器的View设置相关layout_XXX属性是没有任何意义的。

    使用View的getWidth()和getHeight()方法来获取View测量的宽高,必须保证这两个方法在onLayout流程之后被调用才能返回有效值。

    onDraw()

    绘制过程就是把view对象绘制到屏幕上,整个draw过程,需要注意如下细节:

    如果该View是一个ViewGroup,则需要递归绘制其所包含的所有子View。

    View默认不会绘制任何内容,真正的绘制都需要自己在子类中实现。

    View的绘制是借助onDraw方法传入的Canvas类来进行的。

    区分View动画和ViewGroup布局动画,前者指的是View自身的动画,可以通过setAnimation添加,后者是专门针对ViewGroup显示内部子视图时设置的动画,可以在xml布局文件中对ViewGroup设置layoutAnimation属性(譬如对LinearLayout设置子View在显示时出现逐行、随机、下等显示等不同动画效果)。

    在获取画布剪切区(每个View的draw中传入的Canvas)时会自动处理掉padding,子View获取Canvas不用关注这些逻辑,只用关心如何绘制即可。

    默认情况下子View的ViewGroup.drawChild绘制顺序和子View被添加的顺序一致,但是你也可以重载ViewGroup.getChildDrawingOrder()方法提供不同顺序。

    参考文档:

    Android Tools 之一 Hierarchy Viewer

    Android应用层View绘制流程与源码分析

    Android应用setContentView与LayoutInflater加载解析机制源码分析

    深入理解Android之View的绘制流程

    Android视图绘制流程完全解析,带你一步步深入了解View二

    相关文章

      网友评论

          本文标题:View绘制流程

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