close

自定義 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中設定,也比較好管理。

如下圖所示:

螢幕快照 2019-12-22 下午2.21.57.png

 

 

Attrs.xml

新增Attribute方式很簡單,當有自定義view之後,方可做這些定義。

1. 在 value 中新增attr的xml  (範例中打成 attr.xml 應該為attrs.xml)

螢幕快照 2019-12-22 下午1.35.41.png

 

2. 在<resources> </resources> 新增 view 屬性

螢幕快照 2019-12-22 下午1.35.17.png

 

新增屬性

以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>
  • 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()
        }
    }
}

TypedArray

在 RingProgressBar init 中,使用 “obtainStyledAttributes” 取得TypedArray。

TypedArray是個很重要的Object, 他可以幫我們做兩件事情

  1. 轉換attr id 與 屬性值的關係
  2. 取得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

arrow
arrow

    Owen Chen 發表在 痞客邦 留言(0) 人氣()