Android:一篇文章帶你徹底梳理自定義View工做流程!

前言

  • 自定義ViewAndroid 開發者必須瞭解的基礎
  • 網上有大量關於自定義View 原理的文章,但存在一些問題:內容不全、思路不清晰、無源碼分析、簡單問題複雜化等等
  • 今天,我將全面總結自定義View 的原理,我能保證這是市面上的最全面、最清晰、最易懂的
  1. 本文秉着「結論先行、詳細分析在後」的原則,即先讓你們感性認識,再經過理性分析從而理解問題;
  2. 因此,請各位讀者先記住結論,再往下繼續看分析;
  3. 文章較長,閱讀須要較長時間,建議收藏等充足時間再進行閱讀

目錄

示意圖


1. 儲備知識

1.1 ViewRoot

  • 定義 鏈接器,對應於ViewRootImplandroid

  • 做用bash

    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,再傳遞到Viewspa

  • 特別說明 內含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原理系列orm


2. 繪製準備

  • 回憶上圖,可看出最後1步 = 繪製 cdn

    示意圖

  • 但在繪製前,系統會有一些繪製準備,即前面幾個步驟:建立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. 總結

本文全面總結自定義View 的原理。至此,關於自定義View的繪製流程您應該很是熟悉了。關於自定義View的其餘文章:

(1)自定義View基礎 - 最易懂的自定義View原理系列

(2)自定義View Measure過程 - 最易懂的自定義View原理系列

(3)自定義View Layout過程 - 最易懂的自定義View原理系列

(4)自定義View Draw過程- 最易懂的自定義View原理系列

接下來我將繼續對自定義View的應用進行講解,有興趣的能夠繼續關注Carson_Ho的安卓開發筆記


請點贊!由於大家的贊同/鼓勵是我寫做的最大動力!

相關文章
相關標籤/搜索