建立自訂檢視畫面元件

試用 Compose
Jetpack Compose 是 Android 推薦的 UI 工具包。瞭解如何在 Compose 中使用版面配置。

Android 提供複雜且強大的元件化模型,可根據 基本的版面配置類別 「View」和 ViewGroup。這個平台包含 各種預先建立的 ViewViewGroup 子類別,稱為小工具 可讓您用來建構 UI。

部分可用小工具清單包括 ButtonTextViewEditTextListViewCheckBoxRadioButtonGallerySpinner,以及專用 AutoCompleteTextViewImageSwitcherTextSwitcher

以下是可用的版面配置 LinearLayout, FrameLayout, RelativeLayout, 等等。如需更多範例,請參閱 常見版面配置

如果預建的小工具或版面配置都不符合您的需求,您可以自行建立 View 子類別。如果您只需要微調現有小工具 版面配置,您可以為小工具或版面配置建立子類別,並覆寫其方法。

建立自己的 View 子類別可讓您精確控制外觀和 函式。如要瞭解自訂檢視區塊的控制項,請參閱 用途說明:

  • 您可以建立完全自訂的 View 類型,例如「磁碟區」 控制」使用 2D 圖形算繪的旋鈕,類似類比電子控制項。
  • 您可以將一組 View 元件合併為一個新的單一元件 讓方塊變成一個方塊 (結合彈出式清單和任意輸入文字欄位), 雙窗格選取器控制項 (左側和右側窗格中含有清單,每個可重新指派清單) 清單內的項目等
  • 您可以覆寫 EditText 元件在畫面上的算繪方式。 NotePad 範例應用程式可利用這項做法建立內嵌的記事本頁面,
  • 您可以擷取其他事件 (例如按鍵操作),並以自訂方式處理,例如 這一切都歸功於遊戲

以下章節將說明如何建立自訂檢視畫面,並在應用程式中使用。適用對象 詳細的參考資訊,請參閱 View 類別。

基本方法

以下概略說明建立自己的 View 的所有須知事項 元件:

  1. 使用您自己的類別擴充現有的 View 類別或子類別。
  2. 覆寫父類別中的某些方法。要覆寫的父類別方法開頭是 on:例如 onDraw(), onMeasure(), 和 onKeyDown()。 這與之前的on事件類似 Activity 或 你ListActivity的 生命週期和其他功能掛鉤覆寫值。
  3. 使用新的擴充功能類別。完成後,您可以使用新的擴充功能類別取代 以及相關聯的資料檢視
,瞭解如何調查及移除這項存取權。

完全自訂元件

您可以建立完全自訂的圖形元件 您可能會希望圖形 VU 計量器看起來像是舊式類比測量儀,或伴唱文字檢視區塊 會跟著卡拉 OK 機一起唱,不斷跳動的球在文字上移動。您可能會想要 但無論組合方式為何,內建元件都無法辦到。

幸好,您可以建立元件,提供您想要的外觀和運作方式,而僅限於 請記住您的想像力、螢幕大小及可用的處理能力 執行 可能比電腦耗電量明顯低的項目 工作站

如要建立完全自訂的元件,請考慮下列幾點:

  • 您可擴充的最一般檢視區塊為 View,因此通常一開始需先擴充 即可建立新的超級元件
  • 您可以提供建構函式,從 XML 取得屬性和參數,然後您可以 使用您自己的屬性和參數,例如 VU 計量器的顏色和範圍 所需的寬度和阻尼
  • 您可能會想要建立自己的事件監聽器、屬性存取子和修飾符 在元件類別中建立更複雜的行為
  • 您幾乎可以覆寫 onMeasure(),也需要 如果您想讓元件顯示某些內容,請覆寫 onDraw()。雖然兩者都有 預設行為,預設的 onDraw() 不會執行任何動作,而預設行為 onMeasure() 一律會設定 100x100 的大小,您可能不想要這樣。
  • 您也可以視需要覆寫其他 on 方法。

擴充 onDraw() 和 onMeasure()

onDraw() 方法會提供 Canvas,您可以點選這些圖示 例如 2D 圖形、其他標準或自訂元件、樣式化文字 任何你想到的題材都可以嘗試

onMeasure() 有點複雜。「onMeasure()」是非常重要的一環 設定元件與元件容器之間的轉譯合約onMeasure()必須 以便有效且精確地回報所含零件的測量結果。這是 因為父項的限制規定會略為複雜,而這個限制會傳至 onMeasure() 方法),以及呼叫 setMeasuredDimension() 方法,這些項目會經過測量的寬度和高度 如果您未透過覆寫的 onMeasure() 方法呼叫這個方法, 導致測量作業發生例外狀況

大致來說,實作 onMeasure() 看起來會像這樣:

  • 使用寬度和高度呼叫覆寫的 onMeasure() 方法 將視為寬度和高度限制的規定 評估成效「widthMeasureSpec」和「heightMeasureSpec」 參數都是代表尺寸的整數代碼。模型的完整參考資料 請參閱 View.onMeasure(int, int) 這份參考說明文件也解釋了整個評估作業。
  • 元件的 onMeasure() 方法會計算測量寬度和高度 來轉譯元件必須避免使用傳遞的規格 但可能會超過在這種情況下,家長可以選擇要執行的操作,包括 剪輯、捲動、擲回例外狀況,或要求 onMeasure() 再試一次 測量的規格各有不同
  • 計算寬度和高度時,呼叫 setMeasuredDimension(int width, int height) 方法,並計算完成 測量資料否則將出現例外狀況。

以下摘要列出架構在檢視區塊上呼叫的其他標準方法:

類別 方法 說明
創作 建構函式 透過程式碼建立檢視畫面時,系統會呼叫一種形式的建構函式 系統透過版面配置檔案加載檢視畫面時,會呼叫的表單。第二份表單 剖析並套用版面配置檔案中定義的屬性。
onFinishInflate() 在從 XML 加載檢視區塊及其所有子項之後呼叫。
版面配置 onMeasure(int, int) 呼叫此項以確定該檢視區塊及其所有子項的大小要求。
onLayout(boolean, int, int, int, int) 當這個檢視區塊必須將大小和位置指派給其所有子項時呼叫。
onSizeChanged(int, int, int, int) 當這個檢視區塊的大小變更時呼叫。
繪圖 onDraw(Canvas) 當檢視區塊必須轉譯其內容時呼叫。
事件處理 onKeyDown(int, KeyEvent) 在發生按鍵向下事件時呼叫。
onKeyUp(int, KeyEvent) 在發生按鍵抬起事件時呼叫。
onTrackballEvent(MotionEvent) 發生軌跡球動作事件時呼叫。
onTouchEvent(MotionEvent) 在觸控螢幕動作事件發生時呼叫。
突顯重點 onFocusChanged(boolean, int, Rect) 當檢視區塊獲得或失去焦點時呼叫。
onWindowFocusChanged(boolean) 當包含檢視畫面的視窗獲得或失去焦點時呼叫。
附加 onAttachedToWindow() 當檢視區塊附加至視窗時呼叫。
onDetachedFromWindow() 當檢視區塊從視窗卸離時呼叫。
onWindowVisibilityChanged(int) 當包含檢視區塊的視窗可見性變更時呼叫。

複合控制項

如果不想建立完全自訂的元件, 由一組現有控制項組成可重複使用的元件,接著建立複合元件 元件 (或複合控制項) 可能是最佳選擇。總結來說 不可分割的控制項或檢視畫面分為一個邏輯項目群組,只可視為單一項目。 舉例來說,組合方塊可以是單行 EditText 欄位的組合 旁邊的按鈕則包含彈出式清單。如果使用者輕觸按鈕,然後從中選 清單會填入 EditText 欄位,但也可以輸入 也可以直接傳入 EditText

在 Android 中,您還可以使用 Spinner 和另外兩種檢視區塊來達到此目的: AutoCompleteTextView。無論如何,這個組合方塊的概念就是個很好的例子。

如要建立複合元件,請按照下列步驟操作:

  • Activity 一樣,請採用宣告式 (基於 XML) 方法。 即可建立內含的元件,或是透過程式輔助方式從程式碼嵌入元件。 一般的起點是某種 Layout,因此請建立可擴充 Layout。如果是連續方塊,您可以使用 LinearLayout,搭配 水平方向您可以在內部建立其他版面配置的巢狀結構,因此複合元件可以 任意複雜且結構化的方式
  • 在新類別的建構函式中,擷取父類別預期的參數,並傳遞 傳遞至父類別建構函式接著,您可以設定其他資料檢視 新的元件內您可以在這裡建立 EditText 欄位 彈出式視窗清單。您可能會在 XML 中自行加入自己的屬性和參數 建構函式可以提取及使用。
  • 或者,您也可以為內含的檢視區塊可能產生的事件建立事件監聽器。例如 清單項目點擊事件監聽器的接聽程式方法,以更新 如果已選取清單,則為 EditText
  • 您可以選擇使用存取子和修飾符建立自己的屬性。舉例來說,讓 一開始,請在元件中設定 EditText 值,並查詢其內容, 。
  • 視需要覆寫 onDraw()onMeasure()。通常不必在 擴充 Layout,因為版面配置有可能可以正常運作的預設行為。
  • 視需要覆寫其他 on 方法 (例如 onKeyDown()),例如選擇 使用者輕觸特定按鍵時,下拉式方塊的彈出式清單中會提供預設值。

使用 Layout 做為自訂控制項的基礎有很多好處 包括:

  • 您可以使用宣告式 XML 檔案指定版面配置,就像活動畫面一樣。 或者,您也可以透過程式輔助方式建立檢視畫面,然後從程式碼中以巢狀方式將檢視畫面建立巢狀結構中。
  • onDraw()onMeasure() 方法,以及大多數其他方法 on 方法,產生合適的行為,因此您不需要覆寫這些方法。
  • 你可以快速建構任意複雜的化合物檢視畫面,並重複使用這些圖像,就像是一般人 單一元件

修改現有檢視畫面類型

如果有元件您想要的元件,您可以擴充該元件並覆寫 您要變更的行為您可透過完全自訂的 但先在 View 階層中使用更專業的類別,您就可以 取得讓您免費瀏覽的行為。

舉例來說, 記事本 範例應用程式示範了使用 Android 平台的許多層面。其中之一是擴充 EditText 檢視畫面可建立內嵌記事。這並不是最完美的範例,而針對 這可能會改變,不過代表了原則

如果您尚未將 NotePad 範例匯入 Android Studio 或查看 請參閱 LinedEditText 的定義 的 NoteEditor.java 檔案。

在這個檔案中,需要留意以下事項:

  1. 定義

    該類別的定義如下:
    public static class LinedEditText extends EditText

    LinedEditText 定義為 NoteEditor 中的內部類別 但會設為公開,因此使用者也能以 NoteEditor.LinedEditText 的身分存取資料 在 NoteEditor 類別之外。

    此外,LinedEditTextstatic,表示不會產生 所謂「合成方法」,從父項類別存取資料也就是說 的行為是個別類別,而不是與 NoteEditor 密切相關的類別。 如果內部類別不需要從 外部類別能縮減產生的類別,並方便與其他類別 類別

    LinedEditText 會擴充 EditText,這是要自訂的檢視區塊 本例中。完成後,新類別便可取代一般 EditText 檢視畫面。

  2. 類別初始化

    如同往常,系統會先呼叫父類別。這不是預設建構函式 參數化一值EditText 會使用這些參數建立 從 XML 版面配置檔案加載。因此,建構函式必須擷取這些程式碼,並傳遞至 父類別建構函式

  3. 已覆寫的方法

    這個範例只會覆寫 onDraw() 方法,但您可能需要覆寫 讓您自行建立自訂元件

    在這個範例中,覆寫 onDraw() 方法後,即可將藍線繪製在 EditText 檢視畫面面板。畫布會傳入遭到覆寫的設定 onDraw() 方法。super.onDraw() 方法在 方法結束。必須叫用父類別方法。在此情況下,請在 繪製要納入的線條

  4. 自訂元件

    現在您已擁有自訂元件,但要如何使用呢?在 NotePad 範例中, 我們會直接從宣告式版面配置使用自訂元件 note_editor.xmlres/layout 資料夾:

    <view xmlns:android="http://schemas.android.com/apk/res/android"
        class="com.example.android.notepad.NoteEditor$LinedEditText"
        android:id="@+id/note"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        android:padding="5dp"
        android:scrollbars="vertical"
        android:fadingEdge="vertical"
        android:gravity="top"
        android:textSize="22sp"
        android:capitalize="sentences"
    />
    

    自訂元件會建立做為 XML 中的一般檢視區塊,並指定 類別 使用完整套件系統會使用 NoteEditor$LinedEditText 標記法,這是參照內部標記的標準方式 Java 程式設計語言中的類別

    如果自訂檢視區塊元件並未定義為內部類別,您可以宣告檢視區塊 含有 XML 元素名稱的元件,並排除 class 屬性。適用對象 範例:

    <com.example.android.notepad.LinedEditText
      id="@+id/note"
      ... />
    

    可以看到,LinedEditText 類別現已成為獨立的類別檔案。當 類別位於 NoteEditor 類別中,這項技術無法運作。

    定義中的其他屬性和參數則是傳遞至自訂範圍中的屬性和參數 接著傳遞至 EditText 建構函式,因此 和您在 EditText 檢視畫面中使用的參數相同。您可以 您也需要自己的參數

建立自訂元件也依需求那麼複雜。

更複雜的元件可以覆寫更多的 on 方法,並導入其 自己的輔助方法可大幅自訂屬性和行為。唯一的限制是 以及元件需要執行的操作