建立檢視畫面類別

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

設計良好的自訂檢視區塊就像任何其他設計精良的類別一樣。它以簡單的介面封裝一組特定功能,並有效率地使用 CPU 和記憶體等等。除了設計經過妥善設計的類別外,自訂檢視區塊也必須執行以下操作:

  • 符合 Android 標準。
  • 提供可與 Android XML 版面配置搭配使用的自訂樣式屬性。
  • 傳送無障礙功能事件。
  • 與多個 Android 平台相容。

Android 架構提供一組基礎類別和 XML 標記,協助您建立符合上述所有要求的檢視畫面。本課程將說明如何使用 Android 架構,為檢視區塊類別建立核心功能。

您可以在自訂檢視區塊元件中找到其他資訊。

將檢視畫面設為子類別

Android 架構中定義的所有檢視區塊類別都會擴充 View。您的自訂檢視區塊也可以直接擴充 View,您也可以擴充其中一個現有的檢視畫面子類別 (例如 Button),以節省時間。

如要允許 Android Studio 與檢視畫面互動,您至少必須提供可接受 ContextAttributeSet 物件做為參數的建構函式。此建構函式允許版面配置編輯器建立及編輯檢視畫面的例項。

Kotlin

class PieChart(context: Context, attrs: AttributeSet) : View(context, attrs)

Java

class PieChart extends View {
    public PieChart(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

定義自訂屬性

如要將內建 View 新增至使用者介面,請在 XML 元素中指定該內建項目,並使用元素屬性控制其外觀與行為。您也可以使用 XML 新增自訂檢視區塊及設定自訂樣式。如要在自訂檢視畫面中啟用這項行為,請按照下列步驟操作:

  • <declare-styleable> 資源元素中為檢視畫面定義自訂屬性。
  • 在 XML 版面配置中指定屬性值。
  • 在執行階段擷取屬性值。
  • 將擷取的屬性值套用至檢視畫面。

本節會說明如何定義自訂屬性及指定值。下一節將介紹在執行階段擷取及套用值。

如要定義自訂屬性,請在專案中加入 <declare-styleable> 資源。您可以自行將這些資源放入 res/values/attrs.xml 檔案。以下是 attrs.xml 檔案的範例:

<resources>
   <declare-styleable name="PieChart">
       <attr name="showText" format="boolean" />
       <attr name="labelPosition" format="enum">
           <enum name="left" value="0"/>
           <enum name="right" value="1"/>
       </attr>
   </declare-styleable>
</resources>

這個程式碼宣告了兩個自訂屬性 showTextlabelPosition,這些屬性屬於名為 PieChart 的可樣式實體。按照慣例,可設定實體的名稱會與定義自訂檢視畫面的類別名稱相同。雖然您不一定要遵循這項慣例,但許多熱門程式碼編輯器都依賴於這項命名慣例來提供完整陳述式。

定義自訂屬性後,您就可以在版面配置 XML 檔案中使用這些屬性,就像內建屬性一樣。唯一的差別在於自訂屬性屬於不同的命名空間。這些屬性不屬於 http://schemas.android.com/apk/res/android 命名空間,而是屬於 http://schemas.android.com/apk/res/[your package name]。例如,以下說明如何使用為 PieChart 定義的屬性:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:custom="http://schemas.android.com/apk/res-auto">
 <com.example.customviews.charting.PieChart
     custom:showText="true"
     custom:labelPosition="left" />
</LinearLayout>

為避免必須重複長的命名空間 URI,這個範例會使用 xmlns 指令。這個指令會將別名 custom 指派給命名空間 http://schemas.android.com/apk/res/com.example.customviews。您可以為命名空間選擇任何別名。

請注意,用於將自訂檢視區塊新增至版面配置的 XML 標記名稱。這是自訂檢視區塊類別的完整名稱。如果檢視區塊類別是內部類別,請使用檢視畫面的外部類別名稱進一步驗證該類別。舉例來說,PieChart 類別有一個名為 PieView 的內部類別。如要使用這個類別的自訂屬性,請使用 com.example.customviews.charting.PieChart$PieView 標記。

套用自訂屬性

透過 XML 版面配置建立檢視畫面時,XML 標記中的所有屬性都會從資源套件讀取,並以 AttributeSet 形式傳遞至檢視畫面的建構函式。雖然您也可以直接從 AttributeSet 讀取值,但這麼做有一些缺點:

  • 系統不會解析屬性值中的資源參照。
  • 未套用樣式。

請改為將 AttributeSet 傳遞至 obtainStyledAttributes()。這個方法會傳回已解除參照和設定樣式的 TypedArray 值陣列。

Android 資源編譯器會執行大量工作,讓您更輕鬆地呼叫 obtainStyledAttributes()。對於 res/ 目錄中的每個 <declare-styleable> 資源,產生的 R.java 會同時定義屬性 ID 陣列和一組常數,用於定義陣列中每項屬性的索引。並使用預先定義的常數來讀取 TypedArray 中的屬性。以下是 PieChart 類別讀取其屬性的方式:

Kotlin

init {
    context.theme.obtainStyledAttributes(
            attrs,
            R.styleable.PieChart,
            0, 0).apply {

        try {
            mShowText = getBoolean(R.styleable.PieChart_showText, false)
            textPos = getInteger(R.styleable.PieChart_labelPosition, 0)
        } finally {
            recycle()
        }
    }
}

Java

public PieChart(Context context, AttributeSet attrs) {
   super(context, attrs);
   TypedArray a = context.getTheme().obtainStyledAttributes(
        attrs,
        R.styleable.PieChart,
        0, 0);

   try {
       mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
       textPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
   } finally {
       a.recycle();
   }
}

請注意,TypedArray 物件是共用資源,使用後必須回收。

新增資源和事件

屬性是控制檢視畫面行為和外觀的強大方法,但只有在檢視畫面初始化時才能讀取。如要提供動態行為,請為每個自訂屬性公開屬性 getter 和 setter 組合。下列程式碼片段顯示 PieChart 如何公開名為 showText 的屬性:

Kotlin

fun isShowText(): Boolean {
    return mShowText
}

fun setShowText(showText: Boolean) {
    mShowText = showText
    invalidate()
    requestLayout()
}

Java

public boolean isShowText() {
   return mShowText;
}

public void setShowText(boolean showText) {
   mShowText = showText;
   invalidate();
   requestLayout();
}

請注意,setShowText 會呼叫 invalidate()requestLayout()。這些呼叫非常重要,可確保檢視區塊能穩定運作。檢視畫面一經變更可能變更外觀,您需要撤銷該檢視畫面,讓系統知道需要重新繪製。同樣地,如果屬性改變可能會影響檢視畫面的大小或形狀,您就必須要求新的版面配置。忘記這些方法呼叫可能會導致難以發現的錯誤。

自訂檢視畫面也必須支援事件監聽器,用來傳送重要事件。舉例來說,PieChart 會公開名為 OnCurrentItemChanged 的自訂事件,告知事件監聽器使用者旋轉圓餅圖,將焦點放在新的圓餅區塊上。

您很容易忘記公開屬性和事件,如果您是自訂檢視區塊的唯一使用者,更是如此。花些時間仔細定義檢視畫面介面,可減少日後的維護費用。建議您一律公開任何會影響自訂檢視區塊外觀或行為的屬性。

將無障礙設計納入設計考量

自訂檢視畫面必須支援各種使用者。包括阻礙他們觀看或使用觸控螢幕的身心障礙使用者。為協助身心障礙使用者,您可以執行下列操作:

  • 請使用 android:contentDescription 屬性為輸入欄位加上標籤。
  • 視情況呼叫 sendAccessibilityEvent() 來傳送無障礙功能事件。
  • 支援替代控制器,例如 D-Pad 或軌跡球。

如要進一步瞭解如何建立無障礙檢視畫面,請參閱「 提高應用程式的無障礙程度」。