1. 程式人生 > >Android自定義View之自定義屬性

Android自定義View之自定義屬性

在Android開發中經常會用到自定義View的情況,而在自定義View時,自定義屬性是必須用到的。

1、新建一個自定義View如CustomView

它的自定義屬性主要是通過declare-styleable標籤為其配置自定義屬性。具體做法是:在res/values/目錄下增加一個resources xml檔案,示例如下(res/values/attrs.xml)(屬性值如字型、顏色、大小等需要傳遞到程式碼中獲取並使用

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomView">
        <attr name="textString" format="string"/>
        <attr name="colorValue" format="color"/>
        <attr name="textSize" format="dimension"/>
    </declare-styleable>
</resources>

在attrs.xml檔案中,外層引入瞭如下標籤:

<declare-styleable name="CustomView">

解釋:

所有resources檔案中宣告的屬性都會在R.attr類中生成對應的成員變數:

public final class R{
    public static final class attr{
        public static final int textString=0x7f010038;
        public static final int colorValue=0x7f010039;
        public static final int textSize=0x7f010040;
    }
}

但是宣告在標籤中的屬性,系統還會在R.styleable類中生成相關的成員變數

public static final class styleable{
    public static final int[] CustomView={
        0x7f010038,0x7f010039,0x7f010040
    };
    public static final int CustomView_textString=0;
    public static final int CustomView_colorValue=1;
    public static final int CustomView_textSize=2;
}

可以看出R.styleable.CustomView是一個陣列,其中的元素值恰好就是R.attr.textString~textSize的值。而下面的CustomView_textString~CustomView_textSize正好就是其對應的索引

2、編寫佈局檔案,引用自定義的View

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@color/BgColor"
        

    <com.example.CustomView
        android:id="@+id/customView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:colorValue="@color/textRed"
        app:textString="This is the Custom View!!"
        app:textSize="21sp"
        />

</LinearLayout>

注意:

新增佈局檔案的名稱空間

因為我們自定義了View,並且自定義了屬性,而這些屬性不再屬於

http://schema.adnroid.com/apk/res/android

這個名稱空間屬於:

http://schema.android.com/apk/res/[你的專案包名]

所以需要在增加的佈局檔案中的名稱空間改成:

http://schema.adnroid.com/apk/res/com.example

關於自定義View的程式碼,會在下一篇文章中介紹,這裡主要是介紹自定義屬性的細節

format的定義及應用示例:

1、reference:資源引用

屬性定義:

<attr name="background" format="reference"/>

使用示例:

<com.example.CustomView
    android:layout_width="24dp"
    android:layout_height="24dp"
    app:background="@mipmap/bg"
/>

2、color:顏色值

屬性定義:

<attr name="textColor" format="color"/>

使用示例:

<com.example.CustomView
    android:layout_width="24dp"
    android:layout_height="24dp"
    app:textColor="#000000"
 />

3、boolean:布林值

屬性定義:

<attr name="focusable" format="boolean"/>

使用示例:

<com.example.CustomView
    android:layout_width="24dp"
    android:layout_height="24dp"
    app:foucusable="true"
/>

4、dimension:尺寸值

屬性定義:

<attr name="custonWidth" format="demension"/>

屬性使用:

<com.example.CustomView
    app:customWidth="24dp"
    android:layout_height="wrap_content"
/>

5、float:浮點值

屬性定義:

<attr name="fromAlpha" format="float"/>

屬性使用:

<com.example.CustomView
    android:layout_width
    android:layout_height
    app:fromAlpha="0.5"
/>

6、integer:整型值

屬性定義:

<attr name="frameDuration" format="integer"/>

屬性使用:

<com.example.CustomView
    app:frameDuration="12"
/>

7、string:字串

屬性定義:

<attr name="textString" format="string"/>

屬性使用:

<com.example.CustomView
    app:textString="hello world!!"
/>

8、fraction:百分數

屬性定義:

<attr name="pivotX" format="fraction"/>

屬性使用:

<com.example.CustomView
    app:pivotX="30%"
/>

9、列舉值

屬性定義:

<attr name="orientation">
    <enum name="horizontal" value="0"/>
    <enum name="vertical" value="1"/>
</attr>

屬性使用:

<com.example.CustomView
    app:orientation="vertical"
/>

10、flag:位或運算子

屬性定義:

<declare-styleable name="CustomView">
     <attr name="windowSoftInputMode">
           <flag name = "stateUnspecified" value = "0" />
           <flag name = "stateUnchanged" value = "1" />
           <flag name = "stateHidden" value = "2" />
           <flag name = "stateAlwaysHidden" value = "3" />
           <flag name = "stateVisible" value = "4" />
           <flag name = "stateAlwaysVisible" value = "5" />
           <flag name = "adjustUnspecified" value = "0x00" />
           <flag name = "adjustResize" value = "0x10" />
           <flag name = "adjustPan" value = "0x20" />
           <flag name = "adjustNothing" value = "0x30" />
     </attr>         
</declare-styleable>

屬性使用:

<com.example.CustomView
    app:windowSoftInputMode="stateUnspecified|stateUnchanged|stateHidden"
/>

補充:

(2018-12-12)

在程式碼構造器中引用時需要注意TypedArrayAttributeSet這兩個點,例如:

public CustomView(Context context){
    this(context,null);
}

public CustomView(Context context,AttributeSet attrs){
    this(context,attrs,0);
}

public CustomView(Context context,AttributeSet attrs,int defStyleAttr){
    super(context,attrs,defStyleAttr);

    TypedArray array=context.getTheme().obtainStyledAttributes(attrs,R.styleable.CustomView,defStyleAttr);

    int count=array.getIndexCount();
    for(int i=0;i<count;i++){
        switch(i){
            case R.styleable.CustomView_attrs_text://宣告:在styleable中它的名字為attrs_text
                text=array.getString(index);
                break;
            case R.styleable.CustomView_attrs_text_color:
                texcolor=array.getInt(index,Color.BLACK);
                break;
            case  R.styleable.CustomView_attrs_text_size:
                textsize=array.getDimensionPixelSize(index16);
                break;
            ......
    }       







關於TypedArrayAttributeSet

        AttributeSet的作用就是在控制元件進行初始化的時候,解析佈局檔案中該控制元件的屬性(keyeg:background)與該值(valueeg:@drawable/icon)的資訊封裝在AttributeSet中,傳遞給該控制元件的建構函式。

        對於非Android自帶的屬性,在View類中處理時是無法識別的,需要我們自己解析。所以需要用到TypedArray。在AttributeSet中有屬性名稱和屬性值,TypedArray的工作就是來告訴控制元件哪個屬性代表什麼意思。

        TypedArray物件封裝了/values/attrs.xml中的styleable裡定義的每個屬性的型別資訊,通過TypedArray就可以知道AttributeSet中封裝的值的型別,從而可以對這些資料進行應用。