Android官方开发文档Training系列课程中文版:创建自定义View之View的创建
原文地址:http://android.xsoftlab.net/training/custom-views/index.html
引言
Android框架含有大量的View類,這些類用來顯示各式各樣的數據,并可以直接與用戶交互。但是某些時候,APP有一項很特殊的需求,但是框架中的View還不能滿足這樣的需求,這時就需要根據需要自己創建一個全新的View類了。這節課程將會學習如何創建這樣的自定義View。
創建View類
一個設計良好的自定義View與其它任何設計良好的View類都很相似。它封裝了一系列特殊的功能,并將簡單易用的接口暴露了出來。它高效、合理的使用了CPU及內存等資源。除了要實現上面這些特點之外,自定義View還需要:
- 遵循Android標準。
- 提供可以工作于Android XML布局中的自定義樣式屬性。
- 發送可訪問事件。
- Android平臺的兼容性。
Android框架提供了一系列的基礎類及XML標簽來輔助你創建符合以上標準的View。這節課將會學習如何使用Android框架來創建自定義View的核心功能。
創建View的子類
Android中的所有View類都繼承于View。自定義View可以直接繼承View,也可以繼承View子類(比如Button)。
為了使Android Developer Tools可以與你的View產生交互,應當至少提供一個含有Context與AttributeSet作為參數的構造方法。這個構造方法可以使布局編輯器創建或編輯View的實例。
class PieChart extends View {public PieChart(Context context, AttributeSet attrs) {super(context, attrs);} }定義自定義屬性
如果要往UI中添加View,你需要以XML元素的形式指定該View,并通過元素屬性控制View的行為與外貌。定義良好的自定義View還可以通過XML添加、設計這些樣式。為了使自定義View擁有以下這些行為,你必須:
- 在< declare-styleable >資源元素中定義自定義View的屬性。
- 在XML布局中指定屬性的值。
- 在運行時接收屬性值。
- 將接收到的屬性值應用到View中。
這部分將會學習如何定義屬性及如何指定它們的值。下部分會學習在運行時如何處理接收并使用這些值。
要定義自定義屬性,需要在工程中添加< 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的風格實體。風格實體的名字按照慣例與對應的自定義View的類名相一致。盡管不是必須要遵循這項慣例,但很多受歡迎的代碼編輯者都喜歡依照這項命名慣例來提供實現聲明。
一旦定義了自定義屬性,你就可以像內置屬性那樣在XML文件中使用它們。唯一的不同就是,自定義屬性屬于不同的命名空間。它們不屬于標準的http://schemas.android.com/apk/res/android命名空間,而屬于http://schemas.android.com/apk/res/[your package name]。舉個例子,下面是如何使用自定義屬性的示例:
<?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>為了避免重復定義命名空間,示例中使用了xmls指令。該指定使http://schemas.android.com/apk/res/com.example.customviews命名空間與custom別名產生了關聯。你可以為命名空間使用任何你想使用的名稱。
注意,這里在布局中引用的自定義View采用的是自定義View的權限定名。如果View類是個內部類,還必須通過外部類的類名進一步限定。舉個例子, PieChart含有一個名叫PieView的內部類。如果要為這個類使用自定義屬性,你應該使用標簽:com.example.customviews.charting.PieChart$PieView.
應用自定義屬性
當一個View從XML布局中被創建后,XML標簽中的所有屬性都會被讀取,并通過View的構造方法以AttributeSet的形式傳遞到View中。盡管它可能是直接從AttributeSet中讀取數據的,但是它還是有一些缺點:
- 資源所引用的屬性值不能夠被解析
- 不支持Style
相反的,可以將AttributeSet傳給obtainStyledAttributes()方法。該方法會返回一個TypedArray對象,它內部包含了被間接引用的數組值。
Android資源編譯器為了使使用obtainStyledAttributes()方法更加簡便做了大量的工作。在資源目錄中的每一個資源都會在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是一個共享資源,必須在使用完之后對其進行回收。
添加屬性及事件
Attributes是控制View的外觀與行為的一種強大的方式,但是它只有在View初始化的時候才會被讀取。如果要提供動態的行為,則需要暴露相應的get,set方法。下面的代碼展示了PieChart是如何暴露名為showText的屬性方法的:
public boolean isShowText() {return mShowText; } public void setShowText(boolean showText) {mShowText = showText;invalidate();requestLayout(); }注意在setShowText中調用了invalidate()方法與requestLayout()方法。這些方法可以確保View的行為更改生效。在更改完成屬性之后不得不重新繪制該View,這樣才能使View的外觀生效。這樣系統才會知道該View需要重新繪制。同樣的,如果新屬性值可能會引起尺寸或者形狀的更改還需要請求新的布局。忘記調用這些方法會引起很難發現的Bug.
自定義View還應當支持事件監聽器,以便與重要的事件交互。比如,PieChart暴露一個名為OnCurrentItemChanged的自定義事件,用來通知監聽器用戶旋轉了餅圖。
很容易忘記暴露屬性和事件,尤其你是唯一一個自定義View的用戶。在定義View接口時多花點心思可以在將來維護的時候少花點時間和精力。一個良好的習慣就是總是暴露任何成員屬性的外觀與行為的屬性方法。
可訪問性
自定義View應當支持更寬泛的用戶。這其中包括視力有缺陷的殘疾人。為了支持這部分用戶的使用,應當:
- 使用android:contentDescription屬性標識你的輸入字段
- 在適當的時候通過sendAccessibilityEvent()方法發送可訪問事件
- 支持更多的控制器,比如D-pad及軌跡球
有關更多信息請參見 Making Applications Accessible。
閱讀完本篇文章之后,可以繼續閱讀下一篇文章:Android官方開發文檔Training系列課程中文版:創建自定義View之View的繪制
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Android官方开发文档Training系列课程中文版:创建自定义View之View的创建的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pytorch之embedding
- 下一篇: Android如何给无法更改继承关系的A