設計良好的自訂檢視畫面就如同其他設計完善的類別。它具有一組簡易介面、具有效率的 CPU 和記憶體等特定功能,以此類推。除了是設計完善的類別外,自訂檢視區塊也必須執行下列操作:
- 符合 Android 標準。
- 提供適用於 Android XML 版面配置的自訂樣式屬性。
- 傳送無障礙功能事件。
- 與多個 Android 平台相容。
Android 架構提供一組基本類別和 XML 標記,可協助您建立符合所有需求的檢視畫面。本課程將討論如何使用 Android 架構建立檢視畫面類別的核心功能。
詳情請參閱「自訂檢視區塊元件」。
將檢視區塊設為子類別
Android 架構中定義的所有檢視畫面類別都會擴充 View
。自訂檢視區塊也可以直接擴充 View
,或擴充其中一個現有的檢視區塊子類別 (例如 Button
) 以節省時間。
如要允許 Android Studio 與檢視畫面互動,您至少必須提供以 Context
和 AttributeSet
物件做為參數的建構函式。這個建構函式可讓版面配置編輯器建立及編輯檢視區塊的執行個體。
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>
此程式碼會宣告兩個自訂屬性 (showText
和 labelPosition
),屬於名為 PieChart
的可設定實體。根據慣例,可設定樣式實體的名稱會與定義自訂檢視畫面的類別名稱相同。雖然您不需要遵守這個慣例,但許多熱門的程式碼編輯器都仰賴這項命名慣例來提供完成陳述式。
定義自訂屬性後,就和內建屬性一樣,您可以在版面配置 XML 檔案中使用這些屬性。唯一的差別在於自訂屬性屬於其他命名空間。它們屬於 http://schemas.android.com/apk/res/[your package name]
,而不是 http://schemas.android.com/apk/res/android
命名空間。例如,以下說明如何使用針對 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 或軌跡球。
如要進一步瞭解如何建立無障礙檢視畫面,請參閱「 提高應用程式的無障礙程度」一文。