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