例子如下:Android 自訂View 密碼框 例子
1 良好的自訂View
易用,標準,開放。
一個設計良好的自訂view和其他設計良好的類很像。封裝了某個具有易用性介面的功能組合,這些功能能夠有效地使用CPU和記憶體,並且十分開放的。但是,除了開始一個設計良好的類之外,一個自訂view應該:
l 符合安卓標準
l 提供能夠在Android XML布局中工作的自訂樣式屬性
l 發送可訪問的事件
l 與多個Android平台相容。
Android架構提供了一套基本的類和XML標籤來幫您建立一個新的,滿足這些要求的view。忘記提供屬性和事件是很容易的,尤其是當您是這個自訂view的唯一使用者時。請花一些時間來仔細的定義您view的介面以減少未來維護時所耗費的時間。一個應該遵從的準則是:暴露您view中所有影響可見外觀的屬性或者行為。
2 建立自訂View (步驟)2.1 繼承View完全自訂或繼承View的派生子類
必須提供一個能夠擷取Context和作為屬性的AttributeSet對象的建構函式,擷取屬性,當view從XML布局中建立了之後,XML標籤中所有的屬性都從資源套件中讀取出來並作為一個AttributeSet傳遞給view的建構函式。
View 派生出來的直接或間接子類:ImageView, Button, CheckBox, SurfaceView, TextView, ViewGroup, AbsListView
ViewGourp 派生出來的直接或間接子類:AbsoluteLayout, FrameLayout, RelativeLayout, LinearLayout
所有基類、衍生類別都是Android framework層整合的標準系統類別, 可直接引用SDK中這些系統類別及其API
2.2 定義自訂屬性
l 在資源元素<declare-styleable>中為您的view定義自訂屬性。
在項目組添加<declare-styleable>資源。這些資源通常是放在res/values/attrs.xm檔案裡。如下是attrs.xml檔案的一個例子:
1 2 3 4 5 6 7 8 9 |
<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> |
l 在您的XML布局中使用指定屬性的值。
布局XML檔案中可以像內建屬性一樣使用它們。唯一不同是自訂屬性屬於不同的命名空間。
http://schemas.android.com/apk/res/[your package name]
1 2 3 4 5 6 7 |
<?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>
|
l 在運行時取得屬性值。
l 將取回的屬性值應用到您的view中。
2.3 擷取自訂屬性
當view從XML布局中建立了之後,XML標籤中所有的屬性都從資源套件中讀取出來並作為一個AttributeSet傳遞給view的建構函式。儘管從AttributeSet中直接讀取值是可以的,但是這樣做有一些缺點:
l 帶有值的資源引用沒有進行處理
l 樣式並沒有得到允許
取而代之的是,將AttributeSet傳遞給obtainStyledAttributes()方法。這個方法傳回了一個TypedArray數組,包含了已經解除引用和樣式化的值。
為了時能能夠更容易的調用obtainStyledAttributes()方法,Android資源編譯器做了大量的工作。res檔案夾 中的每個<declare-styleable>資源,產生的R.java都定義了一個屬性ID的數組以及一套定義了指向數組中的每一個屬性 的常量。您可以使用預定義的常量從TypedArry中讀取屬性。下例是PieChart類是如何讀取這些屬性的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public PieChart(Context ctx, AttributeSet attrs) { super(ctx, 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(); } } |
注意,TypedArry對象是一個共用的資源,使用完畢必須回收它。
2.4 添加屬性和事件
屬性是控制view的行為和外觀的強有力的方式,但是只有view在初始化後這些屬性才可讀。為了提供動態行為,需要暴露每個自訂屬性的一對getter和setter。下面的程式碼片段顯示PieChart是如何提供showText屬性的。
1 2 3 4 5 6 7 8 9 |
public boolean isShowText() { return mShowText; } public void setShowText(boolean showText) { mShowText = showText; invalidate(); requestLayout(); } |
注意,setShowText調用了invalidate()和requestLayout()。這些調用關鍵是為了保證view行為是可靠的。你必須在改變這個可能改變外觀的屬性後廢除這個view,這樣系統才知道需要重繪。同樣,如果屬性的變化可能影響尺寸或者view的形狀,您需要請求一個新的布局。忘記調用這些方法可能導致難以尋找的bug。
自訂view同樣需要支援和重要事件交流的事件監聽器。
2.5 自訂繪製(實施)
繪製自訂視圖裡最重要的一步是重寫onDraw()方法. onDraw()的參數是視圖可以用來繪製自己的Canvas對象. Canvas定義用來繪製文本、線條、位元影像和其他映像單元. 你可以在onDraw()裡使用這些方法建立你的自訂使用者介面(UI).
android.graphics架構把繪圖分成了兩部分:
l 畫什麼, 由Canvas處理
l 怎麼畫, 由Paint處理
例如, Canvas提供畫線條的方法, 而Paint提供定義線條顏色的方法. Canvas提供畫矩形的方法, 而Paint定義是否用顏色填充矩形或讓它為空白. 簡而言之, Canvas定義你可以在螢幕上畫的形狀, 而Paint為你畫的每個形狀定義顏色、樣式、字型等等.
onDraw()不提供3d圖形api的支援。如果你需要3d圖形支援,必須繼承SurfaceView而不是View,並且通過單獨的線程畫圖。
3 最佳化3.1 降低重新整理頻率
為了提高view的運行速度,減少來自於頻繁調用的程式的不必要的代碼。從onDraw()方法開始調用,這會給你帶來最好的回報。特別地,在onDraw()方法中你應該減少冗餘代碼,冗餘代碼會帶來使你view不連貫的記憶體回收。初始化的冗餘對象,或者動畫之間的,在動畫運行時,永遠都不會有所貢獻。
加之為了使onDraw()方法更有依賴性,你應該儘可能的不要頻繁的調用它。大部分時候調用 onDraw()方法就是調用invalidate()的結果,所以減少不必要的調用invalidate()方法。有可能的,調用四種參數不同類型的invalidate(),而不是調用無參的版本。無參變數需要重新整理整個view,而四種參數類型的變數只需重新整理指定部分的view.這種高效的調用更加接近需求,也能減少落在矩形螢幕外的不必 要重新整理的頁面。
3.2 使用硬體加速
作為Android3.0,Android2D圖表系統可以通過大部分新的Android裝置內建GPU(圖表處理單元)來增加,對於許多應用程式 來說,GPU硬體加速度能帶來巨大的效能增加,但是對於每一個應用來講,並不都是正確的選擇。Android架構層更好地為你提供了控制應用程式部分硬體 是否增加的能力。
怎樣在你的應用,活動,或者表單層級中使用加速度類,請查閱Android開發人員指南中的Hardware Acceleration類。注意到在開發人員指南中的附加說明,你必須在你的AndroidManifest.xml 檔案中的<uses-sdk android:targetSdkVersion="11"/>中將應用目標API設定到11或者更高的層級。
一旦你使用硬體加速度類,你可能沒有看到效能的增長,手機GPUs非常擅長某些任務,例如測量,翻轉,和平移位元影像類的圖片。特別地,他們不擅長其他的任務,例如畫直線和曲線。為了利用GPU加速度類,你應該增加GPU擅長的運算元量,和減少GPU不擅長的運算元量。