原文地址http://developer.android.com/training/custom-views/create-view.html
說在前面的話:第一次翻譯,自知翻譯得不是很好,所以請讀者(如果有讀者的話)不要責怪,我相信以後會做得更好的。
為什麼我要去翻譯,我想原因有以下幾點吧:
- 鍛煉我的英語閱讀的能力
- 通過認真地翻譯,讓我可以對翻譯的內容有更深入的瞭解,可以很好的學習其中的知識。
- 將英文翻譯為中文,可以協助其他一些英語閱讀有困難的人來學習文中的知識(當然了,我現在能力有限,翻譯的東西都是很簡單的,但我希望以後能翻譯一些很好的文中)
建立一個View類一個設計良好的自訂View就像其它任何精心設計的類一樣。它封裝了一組特定的功能,並且有一個容易使用的介面,它還能有效地使用CPU和記憶體等等。儘管如此,除了是一個設計精心的類之外,一個自訂的view還應該
- 符合Android標準
- 提供可以在Android XML布局中使用的自訂屬性
- 發送可訪問的事件(這個翻譯得不是很好,糾結中。。。)
- 能夠相容多個Android平台
Android架構提供了一組基類和XML 標籤來協助你建立一個可以滿足所有這些要求的自訂view。這節課討論的如何使用Android架構來建立一個自訂view的核心功能。繼承一個ViewAndroid架構中定義的所有視圖類都是繼承View類的。你的自訂view也可以直接的繼承View類,或者你可以通過繼承一個已經存在的View的子類比如Button類來節省時間。為了允許Android Developer Tools 與你的view相互配合,你至少提供一個含有一個Context對象和一個AttributeSet對象為參數的構造方法。這個構造方法允許布局編輯器來建立和編輯一個你的視圖的執行個體。
class PieChart extends View { public PieChart(Context context, AttributeSet attrs) { super(context, attrs); }}
定義自訂屬性為了添加一個內建的View到你的使用者介面,你要指定一個XML元素和控制其外貌和行為的元素屬性。精心編寫的自訂視圖也可以通過xml來添加和設定樣式。為了讓你的自訂視圖能夠有這個效果,你必須做到:
- 在一個<declare-styleable>資源元素中為你的視圖自訂屬性
- 在xml布局中制定屬性的值
- 在啟動並執行時候擷取屬性的值
- 使用擷取到的屬性值
這一節將討論如何定義屬性和為它們指定屬性值。下一節將說明在啟動並執行時候處擷取和應用這些屬性值。要定義自訂的屬性,需要添加<declare-styleable>資源到你的項目中。習慣性的將這些<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的styleable 實體。按照慣例,這個styleable實體的名字應和自訂view類的類名一樣。儘管這不是嚴格要求你必須要遵循這個慣例,但是許多流行的代買編輯器都依靠這種命名規範來提供代碼提示。
一旦你自訂的屬性,你就可以像內建的屬性一樣在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/com.example.customviews"> <com.example.customviews.charting.PieChart custom:showText="true" custom:labelPosition="left" /></LinearLayout>
為了避免必須使用很長的命名空間URI,這個例子中使用了一個 xmlns 的指示符,這個指示符分配了一個別名custom給命名空間http://schemas.android.com/apk/res/com.example.customviews ,你可以為你的命名空間取任意的別名。注意將自訂view添加到layout布局中的xml 標籤的名字,它是完全限定自訂view類的名字的。如果你的view類是一個內部類,你需要通過視圖的外部類的名字來進一步限定。進一步,例如,這個PieChart 類有一個內部類PieView,為了使用自訂屬性,你應該使用標籤 com.example.customviews.charting.PieChart$PieView。應用自訂的屬性
當一個視圖由一個XML布局建立的時候,XML標籤中的所有屬性都從資源束中讀取,並且作為一個 AttributeSet對象傳遞到視圖類的構造方法中。雖然可以直接從AttributeSet對象中讀取value值,但是那樣做有一些缺點:
可以將
AttributeSet 傳遞給
obtainStyledAttributes() 來代替,這個方法返回一個已經被引用和添加樣式的
TypedArray 數組值。
Android資源編譯器為你做了許多事情來讓你更容易的調用 obtainStyledAttributes() 。對於每一個<declare-styleable>資源,在R.java檔案中產生了定義了一組屬性id和一組定義了數組中每個元素索引的常量。你用預先定義好的常量來從
TypedArray 對象中讀取屬性值。接下來是PieChart類讀取它的屬性值的例子:
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); mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0); } finally { a.recycle(); }}
注意這個
TypedArray 對象是一個共用的資源,用完之後要回收(recycle)
添加屬性和事件屬性是一種很有力的控制view的行為和介面的方法,但是它們只能在view初始化時被讀取。為了提供動態行為,需要顯示的提供每一個自訂屬性的getter 和 setter方法。下面的程式碼片段展示了PieChart如何暴露showText的屬性:
public boolean isShowText() { return mShowText;}public void setShowText(boolean showText) { mShowText = showText; invalidate(); requestLayout();}
注意在setShowText中調用了 invalidate() 和requestLayout() 方法,這些調用時至關重要的,用來確保view的行為可靠。在任何可能改變視圖外觀的屬性發送改變之後,你必須invalidate
視圖,以至於讓系統知道它需要重新繪製,同樣的,如果一個可能影響視圖的大小或者形狀的屬性改變了,你就需要請求一個新的layout。忘記了這兩個方法的調用,會引起一些難以尋找的bug。自訂view也應該支援事件監聽來傳達重要的事件。例如,PieChart提供了一個叫 OnCurrentItemChanged的自訂的事件來通知監聽者使用者已經旋轉了餅圖從而專註於新的餅圖。很容易忘記提供屬性和事件,特別是當你只是使用自訂view時。請花一些時間來仔細的定義你的介面來減少以後維護的開銷。一個好的可以遵循的規則是總是提供可以影響自訂視圖的形狀或者行為的特性。為體驗設計你自訂的view應該可以支援大範圍的使用者,這些使用者包括那些看不見或者無法觸摸的殘疾人。為了支援這些殘疾使用者,你應該:
- 用android:contentDescription 屬性標註你的輸入框
- 在適當的時候通過調用
sendAccessibilityEvent() 方法來發送可訪問的事件
- 支援備用控制器,比如 D-pad 和 trackball
更多關於建立可訪問的視圖的資訊,你查閱Android Developer Guide中的 Making
Applications Accessible