1. 程式人生 > >Android開發:建立自定義檢視–建立一個View類

Android開發:建立自定義檢視–建立一個View類

翻自:http://developer.android.com/training/custom-views/create-view.html
設計良好的定製檢視與其他精心設計的類相似。它用一種易於使用的介面封裝了一些特殊的方法集合,它高效使用記憶體和CPU等等。除了良好的設計以外,一個定製檢視應該:
符合Android標準
提供定製的可在xml佈局中使用的風格屬性
傳送可訪問性事件(針對盲人等)
相容多個Android平臺

繼承View類
Android框架裡所有的檢視類繼續自View,你的自定義檢視也可以繼續View,或者你可以繼承一個已經存在的View子類節約時間,像Button
為了能讓ADT佈局編輯器能使用你定製的View,你的View必須提供一個Context和 AttributeSet物件作為引數的構造方法(要在xml中用,就必須有這個構造方法)


class PieChart extends View {
    public PieChart(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

定義自定義屬性
給你的UI新增一個內建的View,你可以在xml中通過指定它的屬性,控制它的外觀行為。寫得好的自定義View也可以通過xml新增和設定風格,為了在你的自定義View中啟用這個功能,你必須:
使用元素為你的自定義View定製屬性
在xml佈局中指定屬性值
執行時獲取屬性值
在你的View中應用獲取到的屬性值
本節討論如何定義定製屬性並且指定他們的值,下節處理在執行時獲取並應用這些值
通過新增來定義定製屬性,通常把這些資源放在res/values/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實體。實體的名稱,按照慣例,與自定義View類名相同,儘量沒有嚴格要求必須遵循這個慣例,大多數程式碼編輯器依賴這個命名慣例提供程式碼提示。
一旦你定義了自定義屬性,你可以就像是內建的屬性一樣在xml佈局中使用。唯一的區別是,你的自定義屬性屬於一個不同的名稱空間,他們屬於http://schemas.android.com/apk/res/[包名]名稱空間,而不是系統內建的http://schemas.android.com/apk/res/android。下面是使用屬性的方法:


<?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指令,該指令宣告http://schemas.android.com/apk/res/com.example.customviews名稱空間的一個別名,你可以任何你喜歡的別名。
注意佈局中的xml標籤名,這是自定義View的全名(包括包名),如果你的View類是內部類,你必須使用它的外部類,舉例來說,PieChart有一個叫PieView的內部類,如果要用PieView,你必須標籤com.example.customviews.charting.PieChart$PieView。

應用自定義屬性
當一個View從xml佈局中建立時,xml中的所有屬性都會從資源bundle裡讀取,並作為AttributeSet物件傳給View的構造方法,儘管可以直接從AttributeSet裡讀取這些值,但這麼做有一些不好的地方:
沒有屬性的資源引用不能被解析
樣式沒有應用到View上
作為代替,把AttributeSet傳給obtainStyledAttributes(),這個方法返回一個已經解析好並應用樣式的TypedArray陣列。
為了讓你更容易地呼叫obtainStyledAttributes(),Android資源編譯器做了一大堆工作.res目錄裡的每一個 資源,自動生成的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物件是共享資源,你用完必須回收。

新增屬性和事件
屬性是控制View的行為和外觀的強大工具,當在View初始化時,他們只能被讀取。為了提供動態的行為,可以暴露一個屬性的getter和setter方法。下面的程式碼段展示了PieChart如何暴露showText屬性


public boolean isShowText() {
   return mShowText;
}

public void setShowText(boolean showText) {
   mShowText = showText;
   invalidate();
   requestLayout();
}

注意setShowText呼叫了invalidate()和requestLayout(),這些呼叫是至關重要的,以確保View表現可靠。你必須在改變可能引起View外觀變化的屬性後,使View無效,系統才能知道它需要被重繪。同樣地,如果屬性改變會影響尺寸或形狀,你需要請求一個新的佈局。少了這兩行會產生難以預以發現的BUG。
自定義View也支援事件監聽器與外界通訊。舉例來說,PieChart暴露了一個叫OnCurrentItemChanged的自定義事件,來告訴監聽者使用者翻轉了餅圖,關注了一個新餅圖。
忘記暴露屬性和事件很容易,特別是自定義View只有自己用的時候,多花點時間小心定義你的View介面,減少未來維護成本。一個好的原則是,暴露你的View中所有影響外觀和形為的屬性。

無障礙設計
你的自定義View應該支援最廣泛的使用者,包括看不見,不能使用觸控式螢幕的殘障人士。為了這部分使用者,你應該:
使用android:contentDescription給輸入欄位做標記
在適當的時候通過傳送sendAccessibilityEvent()傳送可訪問性事件
支援備用控制器,如手柄,軌跡球。

© 2014, 冰凍魚. 請尊重作者勞動成果,複製轉載保留本站連結! 應用開發筆記