前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Carson带你学Android:深入解析自定义View工作流程

Carson带你学Android:深入解析自定义View工作流程

作者头像
Carson.Ho
发布2022-03-24 20:48:44
5580
发布2022-03-24 20:48:44
举报
文章被收录于专栏:Android知识分享Android知识分享

前言

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

目录

1. 储备知识

1.1 ViewRoot

  • 定义 连接器,对应于ViewRootImpl
  • 作用
代码语言:txt
复制
1. 连接`WindowManager` 和 `DecorView`
2. 完成`View`的三大流程: `measure`、`layout`、`draw`特别注意
代码语言:javascript
复制
// 在主线程中,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

代码语言:javascript
复制
// 在代码中可通过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基础,具体请看文章:Carson带你学Android:自定义View基础

2. 绘制准备

  • 回忆上图,可看出最后1步 = 绘制
  • 但在绘制前,系统会有一些绘制准备,即前面几个步骤:创建PhoneWindow类、DecorView类、ViewRootmpl类等

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

3. 绘制流程概述

  • 从上可知,View的绘制流程开始于:ViewRootImpl对象的performTraversals()
  • 源码分析
代码语言:javascript
复制
/**
  * 源码分析: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的宽 / 高
  • 在某些情况下,需要多次测量(measure)才能确定View最终的宽/高;
  • 该情况下,measure过程后得到的宽 / 高可能不准确;
  • 此处建议:在layout过程中onLayout()去获取最终的宽 / 高
  • 具体流程

4.2 Layout过程

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

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

  • 具体流程
  • 详细讲解

请看文章:Carson带你学Android:自定义View Layout过程

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,请看文章:Carson带你学Android:手把手教你写一个完整的自定义View

7. 总结

  • 本文全面总结自定义View 的原理。至此,关于自定义View的绘制流程您应该非常熟悉了
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 目录
  • 1. 储备知识
    • 1.1 ViewRoot
      • 1.2 DecorView
        • 1.3 Window、Activity、DecorView 与 ViewRoot的关系
          • 1.4 自定义View基础
          • 2. 绘制准备
          • 3. 绘制流程概述
          • 4. 详细介绍
            • 4.1 Measure 过程
              • 4.2 Layout过程
                • 4.3 Draw过程
                • 5. 自定义View的步骤
                  • 步骤1:实现Measure、Layout、Draw流程
                    • 步骤2:自定义属性
                    • 6. 实例讲解
                    • 7. 总结
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档