發佈在我的網站 http://kesenhoo.github.io/blog/2013/06/30/android-training-ui-creating-custom-views-lesson-1/ ,歡迎訪問!
設計良好的類總是相似的。它使用一個好用的接口來封裝一個特定的功能,它有效的使用CPU與內存,等等。爲了成爲一個設計良好的類,自定義的view應該:
- 遵守Android標準規則。
- 提供自定義的風格屬性值並能夠被Android XML Layout所識別。
- 發出可訪問的事件。
- 能夠兼容Android的不同平臺。
Android的framework提供了許多基類與XML標籤用來幫助你創建一個符合上面要求的View。這節課會介紹如何使用Android framework來創建一個view的核心功能。
Subclass a View
Android framework裏面定義的view類都繼承自View。你自定義的view也可以直接繼承View,或者你可以通過繼承既有的一個子類(例如Button)來節約一點時間。
爲了允許Android Developer Tools能夠識別你的view,你必須至少提供一個constructor,它包含一個Contenx與一個AttributeSet對象作爲參數。這個constructor允許layout editor創建並編輯你的view的實例。
1 2 3 4 5 |
|
Define Custom Attributes
爲了添加一個內置的View到你的UI上,你需要通過XML屬性來指定它的樣式與行爲。爲了實現自定義的view的行爲,你應該:
- 爲你的view在資源標籤下定義自設的屬性
- 在你的XML layout中指定屬性值
- 在運行時獲取屬性值
- 把獲取到的屬性值應用在你的view上
爲了定義自設的屬性,添加 資源到你的項目中。放置於res/values/attrs.xml文件中。下面是一個attrs.xml文件的示例:
1 2 3 4 5 6 7 8 9 |
|
上面的代碼聲明瞭2個自設的屬性,showText與labelPosition,它們都歸屬於PieChart的項目下的styleable實例。styleable實例的名字,通常與自定義的view名字一致。儘管這並沒有嚴格規定要遵守這個convention,但是許多流行的代碼編輯器都依靠這個命名規則來提供statement completion。
一旦你定義了自設的屬性,你可以在layout XML文件中使用它們。唯一不同的是你自設的屬性是歸屬於不同的命名空間。不是屬於http://schemas.android.com/apk/res/android的命名空間,它們歸屬於http://schemas.android.com/apk/res/[your package name]。例如,下面演示瞭如何爲PieChart使用上面定義的屬性:
1 2 3 4 5 6 7 |
|
爲了避免輸入長串的namespace名字,示例上面使用了:custom作爲別名,你也可以選擇其他的名稱所爲你的namespace。
請注意,如果你的view是一個inner class,你必須指定這個view的outer class。同樣的,如果PieChart有一個inner class叫做PieView。爲了使用這個類中自設的屬性,你應該使用com.example.customviews.charting.PieChart$PieView.
Apply Custom Attributes
當view從XML layout被創建的時候,在xml標籤下的屬性值都是從resource下讀取出來並傳遞到view的constructor作爲一個AttributeSet參數。儘管可以從AttributeSet中直接讀取數值,可是這樣做有些弊端(沒有看懂下面的兩個原因):
- 擁有屬性的資源並沒有經過分解
- Styles並沒有運用上
取而代之的是,通過obtainStyledAttributes()來獲取屬性值。這個方法會傳遞一個TypedArray對象,它是間接referenced並且styled的。
請看下面的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
清注意TypedArray對象是一個shared資源,必須被在使用後進行回收。
Add Properties and Events
Attributes是一個強大的控制view的行爲與外觀的方法,但是他們僅僅能夠在view被初始化的時候被讀取到。爲了提供一個動態的行爲,需要暴露出一些合適的getter 與setter方法。下面的代碼演示瞭如何使用這個技巧:
1 2 3 4 5 6 7 8 9 |
|
請注意,在setShowText方法裏面有調用invalidate()) and requestLayout()). 當view的某些內容發生變化的時候,需要調用invalidate來通知系統對這個view進行redraw,當某些元素變化會引起組件大小變化時,需要調用requestLayout方法。
自定義的view也需要能夠支持響應事件的監聽器。例如,PieChart暴露了一個自設的事件OnCurrentItemChanged來通知監聽器,用戶已經切換了焦點到一個新的組件上。
我們很容易忘記了暴露屬性與事件,特別是當你是這個view的唯一用戶時。請花費一些時間來仔細定義你的view的交互。一個好的規則是總是暴露任何屬性與事件。
Design For Accessibility
Your custom view should support the widest range of users. This includes users with disabilities that prevent them from seeing or using a touchscreen. To support users with disabilities, you should:
- Label your input fields using the android:contentDescription attribute
- Send accessibility events by calling sendAccessibilityEvent() when appropriate.
- Support alternate controllers, such as D-pad and trackball
For more information on creating accessible views, see Making Applications Accessible in the Android Developers Guide.