設計良好的自訂檢視區塊就像任何其他設計精良的類別一樣。它以簡單的介面封裝一組特定功能,並有效率地使用 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/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 或軌跡球。
如要進一步瞭解如何建立無障礙檢視畫面,請參閱「 提高應用程式的無障礙程度」。