Android自定義控制元件——自定義屬性
轉載請註明出處:http://blog.csdn.net/allen315410/article/details/39343401
我們在自定義android元件的時候,除了用Java構建出元件的樣子外,有時候還需要去申明一些“屬性”提供給專案使用,那麼什麼是元件的屬性呢?
例如在清單檔案中,建立一個TextView的時候,這是需要制定TextView的android:layout_width="wrap_content" android:layout_height="wrap_content"等等這些都是元件的屬性,TextView是android系統為我們提供好的元件,它的屬性亦是android系統為我們提供了。詳情檢視android的原始碼,我這裡舉例android2.3的原始碼,路徑是/frameworks/base/core/res/res/values/attrs.xml,這個attrs.xml定義了所有android系統元件的屬性。
當我們自定義元件時,除了可以使用android系統為我們提供好的屬性之外,還可以自定義屬性。自定義屬性主要步驟如下:
一、在attrs.xml檔案中宣告屬性,如:
<declare-styleable name="MyToggleBtn"> // 聲名屬性集的名稱,即這些屬性是屬於哪個控制元件的。
<attr name="current_state" format="boolean"/> // 聲名屬性 current_state 格式為 boolean 型別
<attr name="slide_button" format="reference"/> // 聲名屬性 slide_button格式為 reference 型別
</declare-styleable>
所有的format型別reference 引用
color 顏色
boolean 布林值
dimension 尺寸值
float 浮點值
integer 整型值
string 字串
enum 列舉值
二、在佈局檔案中使用:在使用之前必須聲名名稱空間,xmlns:example="http://schemas.android.com/apk/res/com.example.mytogglebtn"
說明:xmlns 是XML name space 的縮寫;
example 可為任意寫符
http://schemas.android.com/apk/res/ 此為android固定格式;
com.example.mytogglebtn 此應用的包名,如manifest配置檔案中一致。
佈局檔案:
<com.example.mytogglebtn.MyToggleButton
xmlns:example="http://schemas.android.com/apk/res/com.example.mytogglebtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
example:slide_button="@drawable/slide_button" />
三、在程式碼中對屬性進行解析,程式碼如下:
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyToggleBtn);// 由attrs 獲得 TypeArray
以上是建立自定義屬性的大致步驟。下面,我將要建立一個自定義控制元件的Demo,來學習學習自定義屬性的相關知識點。
首先,需要建立一個自定義控制元件出來,並且繼承View。在工程的res/values資料夾下建立attrs.xml檔案:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 宣告屬性級的名稱 -->
<declare-styleable name="MyView">
<!-- 宣告一個屬性,整型 -->
<attr name="test_id" format="integer" />
<!-- 宣告一個屬性,字串 -->
<attr name="test_msg" format="string" />
<!-- 宣告一個屬性,引用,引用資源id -->
<attr name="test_bitmap" format="reference" />
</declare-styleable>
</resources>
然後在佈局檔案中,引用這個自定義控制元件MyView
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:example="http://schemas.android.com/apk/res/com.example.myattrs"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.myattrs.MyView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
example:test_bitmap="@drawable/ic_launcher"
example:test_msg="@string/app_name" />
</RelativeLayout>
由於建立出來的自定義元件MyView是繼承於View的,所以必須得複寫View的構造方法,View中有三個構造方法,先來看看複寫帶一個引數的構造方法:
package com.example.myattrs;
import android.content.Context;
import android.view.View;
public class MyView extends View {
public MyView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
}
執行一下工程,那麼工程立即崩潰了,報錯也很清晰明瞭:
09-17 06:52:24.389: E/AndroidRuntime(1563): Caused by: java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.AttributeSet]
表示沒有找到某個帶兩個引數的構造方法,於是,知道自定義屬性必須得複寫父類的另外一個構造方法,修改如下:
package com.example.myattrs;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
public class MyView extends View {
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
int count = attrs.getAttributeCount();
for (int index = 0; index < count; index++) {
String attributeName = attrs.getAttributeName(index);
String attributeValue = attrs.getAttributeValue(index);
System.out.println("name:" + attributeName + " value:" + attributeValue);
}
}
}
列印結果如下:
AttributeSet:對佈局檔案XML解析後的結果,封裝為AttributeSet物件。儲存的都是原始資料,但是對資料進行了簡單的加工。
由此構造器幫我們返回了佈局檔案XML的解析結果,拿到這個結果,我們該怎麼做呢?接下來,我們來看看View類對於這個是怎麼處理的:
public View(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public View(Context context, AttributeSet attrs, int defStyle) {
this(context);
TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
defStyle, 0);
於是,找到一個跟屬性很相關的類TypeArray,那麼接下來,我在自定義控制元件的構造方法上也獲取一下TypeArray這個類:
翻看一下TypeArray的原始碼會發現,TypeArray是不繼承任何類(除了Object)的,也就是說,TypeArray相當於一個工具類,通過context.obtainStyledAttributes方法,將AttributeSet和屬性的型別傳遞進去,比如AttributeSet相當於原材料,屬性型別相當於圖紙,context.obtainStyledAttributes相當於加工廠加工成所物件的屬性,封裝到TypeArray這個類裡。
package com.example.myattrs;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
public class MyView extends View {
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyView);
int count = ta.getIndexCount();
for (int i = 0; i < count; i++) {
int itemId = ta.getIndex(i);
System.out.println("itemId::" + itemId); // 獲取屬性在R.java檔案中的id
switch (itemId) {
case R.styleable.MyView_test_bitmap:
int bitmapId = ta.getResourceId(itemId, 100);
System.out.println("bitmapId::" + bitmapId);
break;
case R.styleable.MyView_test_id:
int test_id = ta.getInteger(itemId, 10);
System.out.println("test_id" + test_id);
break;
case R.styleable.MyView_test_msg:
String test_msg = ta.getString(itemId);
System.out.println("test_msg::" + test_msg);
break;
default:
break;
}
}
}
}
以下是TypeArray類裡的方法,這裡不寫註釋了,見名知意:
當在構造方法中獲取到這些設定好的屬性值時,取出其值,就可以在程式碼中進行處理了。
上篇部落格提到了Android自定義控制元件——仿ios的滑動開關按鈕,接下來,就要為這個滑動開關按鈕條件自定義的屬性,不熟悉上篇部落格Demo的,可以先去瀏覽器一下我的上篇部落格,點這裡Android自定義控制元件——仿ios滑動開關按鈕
首先,按照上面介紹的步驟,先在res/values目錄下建立一個屬性檔案attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyToggleBtn">
<!-- 滑動按鈕背景圖片 -->
<attr name="switchBG" format="reference" />
<!-- 滑動塊圖片 -->
<attr name="slideBg" format="reference" />
<!-- 設定當前的狀態 -->
<attr name="currState" format="boolean" />
</declare-styleable>
</resources>
然後,在引用自定義控制元件的佈局檔案acticity_main.xml上設定自定義屬性,記住,引用這些屬性之前,必須先引用名稱空間:
xmlns:mytogglebtn="http://schemas.android.com/apk/res/com.example.slidebutton"
其中:mytogglebtn 是任意取名,沒有強制要求,但是在控制元件中引用屬性的時候,要保持一致,不要寫錯了
com.example.slidebutton 是工程的包名,千萬不要弄錯了,不然找不到屬性檔案
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:mytogglebtn="http://schemas.android.com/apk/res/com.example.slidebutton"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.slidebutton.view.SlideButton
android:id="@+id/slidebutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
mytogglebtn:currState="false"
mytogglebtn:slideBg="@drawable/slide_button_background"
mytogglebtn:switchBG="@drawable/switch_background" />
</RelativeLayout>
有了上面的步驟,我們就可以自定義元件類的構造方法中,將屬性集解析成TypeArray了,從TypeArray中獲取相關的屬性值,並用於初始化自定義控,以下是主要程式碼:
public SlideButton(Context context, AttributeSet attrs) {
super(context, attrs);
// 獲得自定義屬性
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyToggleBtn);
int count = ta.getIndexCount();
for (int i = 0; i < count; i++) {
int itemId = ta.getIndex(i); // 獲取某個屬性的Id值
switch (itemId) {
case R.styleable.MyToggleBtn_currState: // 設定當前按鈕的狀態
currentState = ta.getBoolean(itemId, false);
break;
case R.styleable.MyToggleBtn_switchBG: // 設定按鈕的背景圖
int backgroundId = ta.getResourceId(itemId, -1);
if (backgroundId == -1)
throw new RuntimeException("資源沒有被找到,請設定背景圖");
switchBG = BitmapFactory.decodeResource(getResources(), backgroundId);
break;
case R.styleable.MyToggleBtn_slideBg: // 設定按鈕圖片
int slideId = ta.getResourceId(itemId, -1);
if (slideId == -1)
throw new RuntimeException("資源沒有找到,請設定按鈕圖片");
slideButtonBG = BitmapFactory.decodeResource(getResources(), slideId);
break;
default:
break;
}
}
}
從上可以看到,自定義屬性其實很簡單。就是在構造方法中,將獲取到的屬性集加工成TypeArray物件,通過這個物件取出屬性的id,通過id取出每個屬性對應的值(畢竟Android下的佈局檔案XML也是key-value形式的),最後將獲取到的屬性值(控制元件使用者自定義的資料)初始化到自定義控制元件上,這樣,一個完整的自定義控制元件就完成。這種完整的自定義控制元件方式用的並不多見,因為在開發自定義控制元件時候,需要什麼資料就直接在Java程式碼裡設定就好了,方便多了。但是在特定的場合下,如果開發的控制元件某些資料不確定,或者所開發控制元件需要提供給其他人進行偏好設定什麼的,這種自定義屬性就顯得非用不可了。
相關文章
- Android自定義控制元件之自定義屬性Android控制元件
- Android自定義組合控制元件之自定義屬性Android控制元件
- android 自定義控制元件 自定義屬性詳細介紹Android控制元件
- 4. 自定義控制元件(4) --- 自定義屬性控制元件
- Android自定義屬性Android
- Android 自定義View:深入理解自定義屬性(七)AndroidView
- 自定義View:自定義屬性(自定義按鈕實現)View
- Android自定義View 屬性新增AndroidView
- .net自定義控制元件下拉的屬性控制元件
- android中自定義屬性重複定義Android
- Android 自定義View:屬性動畫(六)AndroidView動畫
- Android自定義控制元件之自定義組合控制元件Android控制元件
- CSS 自定義屬性指北CSS
- data-* 自定義屬性
- Android開發自定義View之滑動按鈕與自定義屬性AndroidView
- (Android自定義控制元件)Android自定義狀態提示圖表Android控制元件
- 初識css自定義屬性CSS
- CSS 自定義屬性(變數)CSS變數
- 屬性動畫:如何自定義View動畫View
- easyui tree自定義屬性用法UI
- CSS自定義屬性Expression(轉)CSSExpress
- Qt編寫自定義控制元件屬性設計器QT控制元件
- android:建立自定義控制元件Android控制元件
- 【朝花夕拾】Android自定義View篇之(四)自定義View的三種實現方式及自定義屬性詳解AndroidView
- Android 深入理解Android中的自定義屬性Android
- ubuntu下OpenLDAP新增自定義屬性UbuntuLDA
- 使用 CSS 自定義屬性(變數)CSS變數
- 給自定義View新增xml屬性ViewXML
- 【Android】自定義樹形控制元件Android控制元件
- Android自定義控制元件之自定義ViewGroup實現標籤雲Android控制元件View
- css自定義屬性和聚光燈效果CSS
- 【譯】CSS 自定義屬性的策略指南CSS
- spring 自定義屬性解析器Spring
- 帶你深入理解Android中的自定義屬性!!!Android
- C# 自定義屬性在propertyGrid控制元件中顯示C#控制元件
- 自定義Switch控制元件控制元件
- 自定義控制元件ViewPager控制元件Viewpager
- 控制元件自定義位置控制元件