自定義View入門(三) - 自定義屬性

本章目錄

  • Part One:自定義View的屬性

在上一節(jié)中,我們畫出了一個(gè)最基本的圓。不能改變大小、顏色,也不能改變位置。其中,某些屬性我們希望可以讓其它使用者自定義,不指定的話,才使用我們預(yù)先設(shè)置的默認(rèn)值。
所以,這一節(jié)將會(huì)引入自定義View屬性的概念,讓我們的圓繪制的更靈活一些。

Part One:自定義View的屬性

  1. 定義自定義View的屬性
    自定義View屬性通常是寫在res/values/attrs.xml文件中(如果沒(méi)有,請(qǐng)自行創(chuàng)建),整個(gè)結(jié)構(gòu)的標(biāo)準(zhǔn)寫法如下:
<resources>
    <declare-styleable name="CircleView">
        <attr name="circleColor" format="color"/>
        <attr name="radius" format="dimension"/>
        <attr name="strokeWidth" format="dimension"/>
    </declare-styleable>
</resources>

這段代碼聲明了三個(gè)自定義屬性,circleColor(圓環(huán)顏色),radius(半徑)和strokeWidth(圓環(huán)的寬度)。
在<declare-styleable>標(biāo)簽里,name值是為了和其它的自定義View屬性作區(qū)分,起一個(gè)比較好識(shí)別的名字,一般是使用自定義View的類名。也可以不是,不過(guò)android studio會(huì)顯示警告。
另,根據(jù)鴻洋大神所說(shuō):
attrs.xml里面的declare-styleable以及item,android會(huì)根據(jù)其在R.java中生成一些常量方便我們使用(aapt干的),本質(zhì)上,我們可以不聲明declare-styleable僅僅聲明所需的屬性即可。
但是,styleale的出現(xiàn)系統(tǒng)可以為我們完成很多常量(int[]數(shù)組,下標(biāo)常量)等的編寫,簡(jiǎn)化我們的開(kāi)發(fā)工作。
所以最好還是寫上。
在<attr>標(biāo)簽中,name為要設(shè)置的屬性名,format為要設(shè)置的屬性類型。
format表示的屬性類型可以為boolean, string, integer, dimension, float, reference, color, fraction, enum, flag及其混合。
(1) boolean表示布爾值,調(diào)用如 xx:attr1="false"
(2) integer表示整型,調(diào)用如 xx:attr1="1"
(3) dimension表示尺寸值,調(diào)用如 xx:attr1="42dp"
(4) float表示浮點(diǎn)型,調(diào)用如 xx:attr1="0.7"
(5) color表示顏色值,調(diào)用如 xx:attr1="#00FF00"
(6) string表示字符串,調(diào)用如 xx:attr1="#adbddd"
(7) reference表示參考某一資源id,調(diào)用如 xx:attr1 = "@drawable/圖片ID"
(8) fraction表示百分?jǐn)?shù),調(diào)用如 xx:attr1="30%"
混合的話,可以用|分割,比如<attr name="strokeWidth" format="dimension|reference"/>

  1. 獲取并初始化自定義View的屬性
    在attrs.xml中定義好屬性后,這些就會(huì)傳入到自定義View的構(gòu)造方法的AttributeSet類型的參數(shù)中。
    我們可以通過(guò)context.obtainStyledAttributes()方法返回一個(gè)TypedArray對(duì)象。然后用TypedArray對(duì)象獲取自定義View的屬性的值。
    我們這個(gè)案例的代碼如下:
    //圓的半徑
    private float radius;
    //圓的顏色
    private float circleColor;
    //圓的寬度
    private float strokeWidth;
    
    private void initAttrs(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs,
                R.styleable.CircleView, 0, 0);//獲取TypedArray對(duì)象
        radius = typedArray.getDimension(R.styleable.CircleView_radius,
                100);//獲取半徑,默認(rèn)值為100
        strokeWidth = typedArray.getDimension(R.styleable.CircleView_strokeWidth,
                2);//獲取圓環(huán)的寬度,默認(rèn)為2
        circleColor = typedArray.getColor(R.styleable.CircleView_circleColor,
                Color.RED);//獲取圓環(huán)的顏色,默認(rèn)為紅色
        typedArray.recycle();TypedArray對(duì)象是共享的資源,所以在獲取完值之后必須要調(diào)用recycle()方法來(lái)回收。
    }

這里有兩點(diǎn)需要注意:
- TypedArray使用完成后一定要調(diào)用其recycle方法,否則會(huì)有內(nèi)存泄露的問(wèn)題;
- 如果自定義View在一個(gè)單獨(dú)的module中(不屬于主工程),對(duì)attr的獲取不能使用switch-case語(yǔ)句,要用if...else,具體詳見(jiàn):在Android library中不能使用switch-case語(yǔ)句訪問(wèn)資源ID的原因分析及解決方案

  1. 在方法中使用參數(shù)
    使用參數(shù)的方法很簡(jiǎn)單,跟平常的參數(shù)調(diào)用沒(méi)啥區(qū)別。如下圖中所示,修改3處即可。其中,圓心的位置暫時(shí)還是固定的,我們將在自定義View的layout階段優(yōu)化。


    UseAttrs.png
  2. 在xml中設(shè)置屬性
    如下一圖所示,如果我們不在xml布局中設(shè)置自定義View的屬性值時(shí),會(huì)調(diào)用默認(rèn)值,跟上一節(jié)的案例一樣。


    Original.png

    那么,如果使用這些自定義View的屬性呢。

  • 首先,我們要在調(diào)用此控件的XML布局的根標(biāo)簽設(shè)定自定義屬性的命名控件:


    nameSpace.png

    其實(shí)一開(kāi)始系統(tǒng)已經(jīng)為我們創(chuàng)建好了這個(gè)app的命名空間,只不過(guò)一直沒(méi)有使用,下面有個(gè)波浪號(hào)。app的名字可以隨意改變,除了android~

  • 然后呢,使用 命名空間:屬性名 即可
    <com.terana.customview.CircleView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        app:circleColor="#669900"
        app:strokeWidth="8dp"
        app:radius="20dp"/>

再運(yùn)行一遍,可以看到,顏色,大小,還有圓環(huán)的寬度都已經(jīng)改變


AfterUseAttrs.png

至此,有關(guān)自定義View的屬性這塊已經(jīng)完成了。下一節(jié),我們繼續(xù)優(yōu)化它,比如說(shuō)layout_width和layout_height這兩個(gè)屬性,不管設(shè)定什么值,結(jié)果都是一樣的。到底該如何弄呢,看自定義View入門(四).

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容