View繪製01-Android渲染系統中的View

小海編碼日記發表於2020-10-24

Android渲染系統中的View

對於初級開發者而言,在面試中,經常會和麵試官聊到Android四大元件,聊到Activity,其中回答最純熟的一句話就是:

Activity的作用是應用與使用者之間互動的重要元件

那麼Activity之互動功能又是怎麼實現的呢?答案不言而喻-View

我們在Activity onCreate的時候呼叫setContentView方法為Activity設定佈局,實際上就相當於對使用者開放了多個互動介面,使用者可以通過佈局中一個一個的View進行自己想要的操作,我們也可以通過View來向使用者展示結果資訊,那麼View在Android渲染系統中長啥樣呢?

首先我們開啟系統的開發者選項( 通過多次點選 系統設定 > 關於本機中的版本號開啟),找到顯示佈局邊界選項並開啟(如下圖所示),
在這裡插入圖片描述
開啟後,我們可以看到介面上多了很多不同顏色的線框以及矩形蒙版,這些線框圈中的部分就代表著一個View或者ViewGroup,陰影部分顯示的是距父佈局的Margin或者Padding(如下圖所示)。
在這裡插入圖片描述

從上面兩張圖我們可以看到Android渲染系統中以點陣為基本元素,用一個矩形區域來渲染View,同時在這個矩形區域內響應使用者互動,從Android渲染系統角度來看,View就是點陣裡面的一塊矩形區域

Android原始碼中的View

不論是Java還是Kotlin,其語言特性就是物件導向,那麼View作為Android體系中的一部分,毫無疑問,它是一個物件,那麼這個物件有什麼特性呢?我們來看下官方原始碼中的說明:

This class represents the basic building block for user interface components. A View occupies a rectangular area on the screen and is responsible for drawing and event handling. View is the base class for widgets, which are used to create interactive UI components (buttons, text fields, etc.). The
{@link android.view.ViewGroup} subclass is the base class for layouts, which are invisible containers that hold other Views (or other ViewGroups) and define their layout properties.

上面這句話主要闡述瞭如下幾個要點:

  1. View的形狀以及作用:View是螢幕上用於進行資料渲染展示和處理使用者事件的矩形區域,這一點我們通過第一部分渲染系統已充分認識到。
  2. View的頂級父類特性:View是所有元件及Layout的直接或間接父類,這一點我們可以通過繪製各元件類繼承關係認識到(如下圖)。
    在這裡插入圖片描述看了原始碼中關於View的定義,同學們是否對View認識更加清晰了呢?

同學們都知道,Android中有兩種佈局管理方式,通過Java程式碼或者xml佈局檔案(兩者經常組合使用,這裡我們不單獨列出),我們來看下一個典型的java程式碼控制佈局的例子,程式碼如下圖:
在這裡插入圖片描述
這裡我們通過new關鍵詞生成了TextView物件,並將其設定在Activity的佈局上,使用xml佈局方式同樣能開啟上圖右側執行效果,但是TextView物件又是什麼時候生成的呢?這就涉及到AndroidView的管理-View樹,瞭解View樹的建立過程,有利於我們更好的理解Android中的View管理機制,後續文章或小冊中我們將做更詳細的闡述。

Android系統座標系及View座標系

View作為螢幕上一塊用於使用者互動和資料展示的矩形區域,那麼這塊矩形區域的渲染分工是怎麼的呢?又是怎麼確定這塊矩形區域繪製在哪裡呢?聯想數學中,我們在繪製圖形之前,首先會確立什麼?沒錯,座標系。在Android中也有座標系的概念,與View相關的主要有Android螢幕座標系和View座標系,Android螢幕座標系用於系統確認該在什麼位置繪製多大的矩形區域以展示ViewView座標系用於View內部進行自我繪製時確認繪製方向和大小。

Android螢幕座標系如下圖所示,以螢幕左上角為座標原點,向右為X正方向,向下為Y正方向。
在這裡插入圖片描述
View座標系與Android螢幕座標系類似,如下圖所示,只不過其座標原點位於View所在矩形區域的左上角,向右為X正向,向下為Y正向。
在這裡插入圖片描述
從上圖中我們可以看出,所有的ViewLayout內部的座標系均是View座標系,同時也可以看到getTop()getLeft()getRight()以及getBottom()這四個函式具體所對應的距離含義。當我們在View內部進行測量繪製時,經常需要用到這四個函式,通過這四個函式我們可以手動計算該View在介面上矩形區域的寬度和高度(注意這裡描述的是介面上矩形區域,即View的使用者可見部分,在View內部是沒有邊界可言的,理論上講,一個View的內部可以無限繪製)。

可能有同學要問了,你講了View座標系,但是我需要知道View在螢幕座標系中的位置怎麼搞呢?也很簡單,我們可以通過ViewgetBoundsOnScreen(Rect outRect)獲取View在螢幕上的矩形區域,那麼View在螢幕座標系中的位置就顯而易見了。

也許有同學見過重寫onTouchListener,自己攔截事件的操作,這種情況下我們就需要獲取當前觸控點的位置以用於判斷是否進行業務邏輯處理,具體說明如下圖:
在這裡插入圖片描述
從上圖我們可以看出getRawX()getRawY()是觸控點距離螢幕座標系座標原點的距離,getX()getY()是觸控點距離View座標系座標原點的距離,通常情況下,如果是View整體的觸屏事件處理,例如拖動View,點選View,我們選用getRawX()getRawY(),如果是View內部的事件處理,例如進行View***內容***的滾動,我們選用getX()getY()

相關文章