美文网首页UIAndroid开发Android开发
Android:一篇文章带你完全梳理自定义View工作流程!

Android:一篇文章带你完全梳理自定义View工作流程!

作者: Carson带你学安卓 | 来源:发表于2019-07-03 08:44 被阅读344次

    前言

    • 自定义ViewAndroid 开发者必须了解的基础
    • 网上有大量关于自定义View 原理的文章,但存在一些问题:内容不全、思路不清晰、无源码分析、简单问题复杂化等等
    • 今天,我将全面总结自定义View 的原理,我能保证这是市面上的最全面、最清晰、最易懂的
    1. 本文秉着“结论先行、详细分析在后”的原则,即先让大家感性认识,再通过理性分析从而理解问题;
    2. 所以,请各位读者先记住结论,再往下继续看分析;
    3. 文章较长,阅读需要较长时间,建议收藏等充足时间再进行阅读

    目录

    示意图

    1. 储备知识

    1.1 ViewRoot

    • 定义
      连接器,对应于ViewRootImpl

    • 作用

      1. 连接WindowManagerDecorView
      2. 完成View的三大流程: measurelayoutdraw
    • 特别注意

    // 在主线程中,Activity对象被创建后:
    // 1. 自动将DecorView添加到Window中 & 创建ViewRootImpll对象
    root = new ViewRootImpl(view.getContent(),display);
    
    // 3. 将ViewRootImpll对象与DecorView建立关联
    root.setView(view,wparams,panelParentView)
    

    1.2 DecorView

    • 定义:顶层View

    Android 视图树的根节点;同时也是 FrameLayout 的子类

    • 作用:显示 & 加载布局

    View层的事件都先经过DecorView,再传递到View

    • 特别说明
      内含1个竖直方向的LinearLayout,分为2部分:上 = 标题栏(titlebar)、下 = 内容栏(content)
    示意图

    Activity中通过 setContentView()所设置的布局文件其实是被加到内容栏之中的,成为其唯一子View = id为content的FrameLayout

    // 在代码中可通过content得到对应加载的布局
    
    // 1. 得到content
    ViewGroup content = (ViewGroup)findViewById(android.R.id.content);
    // 2. 得到设置的View
    ViewGroup rootView = (ViewGroup) content.getChildAt(0);
    

    1.3 Window、Activity、DecorView 与 ViewRoot的关系

    • 简介
    示意图

    1.4 自定义View基础

    了解自定义View流程前,需了解一定的自定义View基础,具体请看文章:(1)自定义View基础 - 最易懂的自定义View原理系列


    2. 绘制准备

    • 回忆上图,可看出最后1步 = 绘制


      示意图
    • 但在绘制前,系统会有一些绘制准备,即前面几个步骤:创建PhoneWindow类、DecorView类、ViewRootmpl类等

    故,下面我会先将绘制前的准备,再开始讲绘制流程


    3. 绘制流程概述

    • 从上可知,View的绘制流程开始于:ViewRootImpl对象的performTraversals()
    • 源码分析
    /**
      * 源码分析:ViewRootImpl.performTraversals()
      */
      private void performTraversals() {
    
            // 1. 执行measure流程
            // 内部会调用performMeasure()
            measureHierarchy(host, lp, res,desiredWindowWidth, desiredWindowHeight);
    
            // 2. 执行layout流程
            performLayout(lp, mWidth, mHeight);
    
            // 3. 执行draw流程
            performDraw();
        }
    
    • 从上面的performTraversals()可知:View的绘制流程从顶级View(DecorView)ViewGroup开始,一层一层从ViewGroup至子View遍历测绘

    即:自上而下遍历、由父视图到子视图、每一个 ViewGroup 负责测绘它所有的子视图,而最底层的 View 会负责测绘自身

    示意图
    • 绘制的流程 = measure过程、layout过程、draw过程,具体如下
    示意图 示意图

    下面,我将详细讲解View绘制的三大流程:measure过程、layout过程、draw过程


    4. 详细介绍

    4.1 Measure 过程

    • 作用
      测量View的宽 / 高
    1. 在某些情况下,需要多次测量(measure)才能确定View最终的宽/高;
    2. 该情况下,measure过程后得到的宽 / 高可能不准确;
    3. 此处建议:在layout过程中onLayout()去获取最终的宽 / 高
    • 具体流程
    示意图 示意图

    4.2 Layout过程

    • 作用
      计算视图(View)的位置

    即计算View的四个顶点位置:LeftTopRightBottom

    • 具体流程


      示意图
    示意图
    • 详细讲解

    请看文章:自定义View Layout过程 - 最易懂的自定义View原理系列(3)

    4.3 Draw过程

    • 作用
      绘制View视图

    • 具体流程

    示意图 示意图

    至此,关于自定义View的工作流程讲解完毕。


    5. 自定义View的步骤

    步骤1:实现Measure、Layout、Draw流程

    • 从View的工作流程(measure过程、layout过程、draw过程)来看,若要实现自定义View,根据自定义View的种类不同(单一View / ViewGroup),需自定义实现不同的方法
    • 主要是:onMeasure()onLayout()onDraw(),具体如下
    示意图

    步骤2:自定义属性

    1. 在values目录下创建自定义属性的xml文件
    2. 在自定义View的构造方法中加载自定义XML文件 & 解析属性值
    3. 在布局文件中使用自定义属性

    6. 实例讲解

    结合原理 & 实现步骤,若需实现1个自定义View,请看文章:手把手教你写一个完整的自定义View


    7. 总结


    请点赞!因为你们的赞同/鼓励是我写作的最大动力!

    相关文章阅读
    Android事件分发机制详解:史上最全面、最易懂
    Android开发:最全面、最易懂的Android屏幕适配解决方案
    Android开发:史上最全的Android消息推送解决方案
    Android开发:最全面、最易懂的Webview详解
    Android开发:JSON简介及最全面解析方法!
    Android四大组件:Service服务史上最全面解析
    Android四大组件:BroadcastReceiver史上最全面解析


    欢迎关注Carson_Ho的简书!

    不定期分享关于安卓开发的干货,追求短、平、快,但却不缺深度

    相关文章

      网友评论

        本文标题:Android:一篇文章带你完全梳理自定义View工作流程!

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