本章目錄
- Part One:自定義View的屬性
在上一節(jié)中,我們畫出了一個(gè)最基本的圓。不能改變大小、顏色,也不能改變位置。其中,某些屬性我們希望可以讓其它使用者自定義,不指定的話,才使用我們預(yù)先設(shè)置的默認(rèn)值。
所以,這一節(jié)將會(huì)引入自定義View屬性的概念,讓我們的圓繪制的更靈活一些。
Part One:自定義View的屬性
- 定義自定義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"/>
- 獲取并初始化自定義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的原因分析及解決方案
-
在方法中使用參數(shù)
使用參數(shù)的方法很簡(jiǎn)單,跟平常的參數(shù)調(diào)用沒(méi)啥區(qū)別。如下圖中所示,修改3處即可。其中,圓心的位置暫時(shí)還是固定的,我們將在自定義View的layout階段優(yōu)化。
UseAttrs.png -
在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)改變

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


