自定義 View Attribute
上篇 提到自定義view RingProgressBar
其中有些參數,如 ring color. text color, size等,這些不會改變的設定檔,能否在layout中直接定義好,不用在class終在做設定呢
讓自定義view有更方便的 reuse
這篇講解如何自訂義 view 中的屬性
前言
在設定前先說說,自定義有什麼好處?
首先Android Studio 有提供Priview layout 排版的功能。我們可以輕易看出layout中物件的樣式排版是否正確
而在code design中,有高內聚,低耦合(high cohesion、low coupling) 。希望把相關東西放在一起(有點扯遠了)
所以在class中設定相關view的事情,除非不得已, 如: 動態的值或顏色,我是傾向放在view中設定,也比較好管理。
如下圖所示:
Attrs.xml
新增Attribute方式很簡單,當有自定義view之後,方可做這些定義。
1. 在 value 中新增attr的xml (範例中打成 attr.xml 應該為attrs.xml)
2. 在<resources> </resources> 新增 view 屬性
新增屬性
以RingProgressBar為範例
使用 declare-stylealbe 綁定該屬性是誰的
<declare-styleable name="RingProgressBar"> <attr name="bgRingColor" format="color" /> <attr name="bgRingSize" format="dimension" /> <attr name="pRingColor" format="color" /> <attr name="pRingSize" format="dimension" /> <attr name="textSize" /> <attr name="textColor" /> <attr name="RingPadding" format="dimension" /> <attr name="progressValue" format="integer" /> </declare-styleable>
並在其中設定 相關屬性 <attr name="", format="格式"/>
可設定格式頗多種 以下會慢慢介紹
1. 基本類別:
- string
- integer
- float
- boolean
- fraction: 百分比類型, 取直只能以%結尾 (很少用到)
2. resource:
- color
- 使用方式 @color/, "#009900"
- dimension
- 設定數值用,
- reference
- 可從其他resource files重取得值, 如 @string/XXX, @drawable/, @dimen/
3. 特殊類型
- enum 枚舉
- 在定義時,須在該attr節點下面加入enum節點,取值時只能取其中一個。(format 可加可不加)
<attr name="progressSize" format="enum"> <enum name="large" value="2" /> <enum name="small" value="1" /> </attr>
- 在定義時,須在該attr節點下面加入enum節點,取值時只能取其中一個。(format 可加可不加)
- flags
- 以 bit 為標記方式,與enum用法一樣,
- 與enum差別在於 可以透過 “|” 來做計算
<attr name="progressFlags" format="flags"> <flag name="flag_0" value="0"/> <flag name="flag_1" value="1"/> <flag name="flag_2" value="2"/> </attr>
共用屬性
當自定義物件越來越多時,時常會發現某些屬性是相同,想要共用時該怎麼設定
簡單來說只需要做兩件事情
1. 把屬性拉出來,與"<declare-styleable></<declare-styleable>"同一層
2. 在使用該屬性時,不用設定format
Custom View 設定
範例以 koltin 語法寫,
class RingProgressBar @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
...
init {
attrs?.let {
val ta = context.obtainStyledAttributes(attrs, R.styleable.RingProgressBar)
// TODO get value from ta
// ta.getDimension(R.styleable.RingProgressBar_bgRingSize, 20f)
ta.recycle()
}
}
}
在 RingProgressBar init 中,使用 “obtainStyledAttributes” 取得TypedArray。
TypedArray是個很重要的Object, 他可以幫我們做兩件事情
- 轉換attr id 與 屬性值的關係
- 取得layout 中設定的值,取得方式依據該attr format,如 attr format 是 string, 可用getString 取得
詳細方式可去android developer 文件上找尋所有方法
參考
https://developer.android.com/training/custom-views/create-view
https://www.jianshu.com/p/813772e748c6
https://developer.android.com/reference/android/content/res/TypedArray
留言列表