Carson帶你學Android:自定義View基礎必知必會!

前言

  • 自定義View原理是Android開發者必須了解的基礎;
  • 在了解自定義View之前,你需要有一定的知識儲備;
  • 本文將全面解析關于自定義View中的所有知識基礎。

Carson帶你學Android自定義View文章系列:
Carson帶你學Android:自定義View基礎
Carson帶你學Android:一文梳理自定義View工作流程
Carson帶你學Android:自定義View繪制準備-DecorView創建
Carson帶你學Android:自定義View Measure過程
Carson帶你學Android:自定義View Layout過程
Carson帶你學Android:自定義View Draw過程
Carson帶你學Android:手把手教你寫一個完整的自定義View
Carson帶你學Android:Canvas類全面解析
Carson帶你學Android:Path類全面解析


目錄

示意圖

1. 視圖定義

即日常說的View,具體表現為顯示在屏幕上的各種視圖控件,如TextView、LinearLayout等。


2. 視圖分類

視圖View主要分為兩類:

  • 單一視圖:即一個View、不包含子View,如TextView
  • 視圖組,即多個View組成的ViewGroup、包含子View,如LinearLayout

Android中的UI組件都由View、ViewGroup共同組成。


3. 視圖類簡介

  • 視圖的核心類是:View類
  • View類是Android中各種組件的基類,如View是ViewGroup基類
  • View的構造函數:共有4個,具體如下:

自定義View必須重寫至少一個構造函數:

// 構造函數1
// 調用場景:View是在Java代碼里面new的
public CarsonView(Context context) {
    super(context);
}

// 構造函數2
// 調用場景:View是在.xml里聲明的
// 自定義屬性是從AttributeSet參數傳進來的
public  CarsonView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

// 構造函數3
// 應用場景:View有style屬性時
// 一般是在第二個構造函數里主動調用;不會自動調用
public  CarsonView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

// 構造函數4
// 應用場景:View有style屬性時、API21之后才使用
// 一般是在第二個構造函數里主動調用;不會自動調用
public  CarsonView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
}

更加具體的使用請看:深入理解View的構造函數
理解View的構造函數


4. 視圖結構

  • 對于包含子View的視圖組(ViewGroup),結構是樹形結構
  • ViewGroup下可能有多個ViewGroup或View,如下圖:

這里需要特別注意的是:在View的繪制過程中,永遠都是從View樹結構的根節點開始(即從樹的頂端開始),一層一層、一個個分支地自上而下遍歷進行(即樹形遞歸),最終計算整個View樹中各個View,從而最終確定整個View樹的相關屬性。


5. Android坐標系

Android的坐標系定義為:

  • 屏幕的左上角為坐標原點
  • 向右為x軸增大方向
  • 向下為y軸增大方向

具體如下圖:

注:區別于一般的數學坐標系

兩者坐標系的區別

6. View位置(坐標)描述

視圖的位置由四個頂點決定,如圖1-3所示的A、B、C、D。

視圖的位置是相對于父控件而言的,四個頂點的位置描述分別由四個與父控件相關的值決定:

  • 頂部(Top):視圖上邊界到父控件上邊界的距離;
  • 左邊(Left):視圖左邊界到父控件左邊界的距離;
  • 右邊(Right):視圖右邊界到父控件左邊界的距離;
  • 底部(Bottom):視圖下邊界到父控件上邊界的距離。

具體如圖1-4所示。

可根據視圖位置的左上頂點、右下頂點進行記憶:

  • 頂部(Top):視圖左上頂點到父控件上邊界的距離;
  • 左邊(Left):視圖左上頂點到父控件左邊界的距離;
  • 右邊(Right):視圖右下頂點到父控件左邊界的距離;
  • 底部(Bottom):視圖右下頂點到父控件上邊界的距離。

7. 位置獲取方式

視圖的位置獲取是通過View.getXXX()方法進行獲取。

獲取頂部距離(Top):getTop()
獲取左邊距離(Left):getLeft()
獲取右邊距離(Right):getRight()
獲取底部距離(Bottom):getBottom()
  • 與MotionEvent中 get()getRaw()的區別
//get() :觸摸點相對于其所在組件坐標系的坐標
 event.getX();       
 event.getY();

//getRaw() :觸摸點相對于屏幕默認坐標系的坐標
 event.getRawX();    
 event.getRawY();

具體如下圖:

get() 和 getRaw() 的區別

8. 角度(angle)& 弧度(radian)

  • 自定義View實際上是將一些簡單的形狀通過計算,從而組合到一起形成的效果。

這會涉及到畫布的相關操作(旋轉)、正余弦函數計算等,即會涉及到角度(angle)與弧度(radian)的相關知識。

  • 角度和弧度都是描述角的一種度量單位,區別如下圖::
角度和弧度區別

在默認的屏幕坐標系中角度增大方向為順時針。

屏幕坐標系角度增大方向

注:在常見的數學坐標系中角度增大方向為逆時針


9. 顏色相關

Android中的顏色相關內容包括顏色模式,創建顏色的方式,以及顏色的混合模式等。

9.1 顏色模式

Android支持的顏色模式主要包括:

  • ARGB8888:四通道高精度(32位)
  • ARGB4444:四通道低精度(16位)
  • RGB565:Android屏幕默認模式(16位)
  • Alpha8:僅有透明通道(8位)

這里需要特別注意的是:

  • 字母:表示通道類型;
  • 數值:表示該類型用多少位二進制來描述;
  • 示例說明:ARGB8888,表示有四個通道(ARGB);每個對應的通道均用8位來描述。

以ARGB8888為例介紹顏色定義:

ARGB88888

9.2 顏色定義

主要分為xml定義 / java定義。

/**
  * 定義方式1:xml
  * 在/res/values/color.xml文件中定義
  */
  <?xml version="1.0" encoding="utf-8"?>
  <resources>
    //定義了紅色(沒有alpha(透明)通道)
    <color name="red">#ff0000</color>
    //定義了藍色(沒有alpha(透明)通道)
    <color name="green">#00ff00</color>
  </resources>

  // 在xml文件中以”#“開頭定義顏色,后面跟十六進制的值,有如下幾種定義方式:
  #f00  //低精度 - 不帶透明通道紅色      
  #af00 //低精度 - 帶透明通道紅色        
  #ff0000 //高精度 - 不帶透明通道紅色          
  #aaff0000 //高精度 - 帶透明通道紅色       

/**
  * 定義方式2:Java
  */
  // 使用Color類定義顏色
  int color = Color.GRAY; //灰色

  // Color類使用ARGB值表示
  int color = Color.argb(127, 255, 0, 0); //半透明紅色   
  int color = 0xaaff0000; //帶有透明度的紅色                                    

9.3 顏色引用

主要分為xml定義 / java定義。

/**
  * 引用方式1:xml
  */
  // 1. 在style文件中引用
  <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
       <item name="colorPrimary">@color/red</item>
  </style>
  // 2. 在layout文件中引用
  android:background="@color/red"     
  // 3. 在layout文件中創建并使用顏色
  android:background="#ff0000"       

/**
  * 引用方式2:Java
  */
  //方法1
  int color = getResources().getColor(R.color.mycolor);

  //方法2(API 23及以上)
  int color = getColor(R.color.myColor);      

9.4 取色工具

  • 顏色都是用RGB值定義的,而我們一般是無法直觀的知道自己需要顏色的值,需要借用取色工具直接從圖片或者其他地方獲取顏色的RGB值。
  • 有時候一些簡單的顏色選取就不用去麻煩UI了,開發者自己去選取效率更高
  • 這里,取色工具我強推Markman:一款設計師用于標注的工具,主要用于尺寸標注、字體大小標注、顏色標注,而且使用簡單。本人強烈推薦!
Markman

10. 總結


歡迎關注Carson_Ho的簡書

不定期分享關于安卓開發的干貨,追求短、平、快,但卻不缺深度


請點贊!因為你的鼓勵是我寫作的最大動力!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容