Android自定义属性

1,773 阅读3分钟

前言

在自定义View时,经常会在attr.xml文件中自定义属性,例:

<resources>
    <attr name="my_attribute" format="boolean" />

    <declare-styleable name="CircleImageView">
        <attr name="civ_border_width" format="dimension" />
        <attr name="civ_border_color" format="color" />
        <attr name="civ_border_overlay" format="boolean" />
        <attr name="civ_circle_background_color" format="color" />
    </declare-styleable>
</resources>

可在在顶部的<resources>元素中定义attr,也可以在<declare-styleable>中定义attr。如果我们不止在一个地方使用attr,我们可以把它放在<resource>根元素下面,如上图的my_attribute。注意,所有属性共享相同的全局名称空间。这表明即使您在一个<declare-styleable>元素内部创建了一个新的属性,它也可以在元素外部使用,并且您不能创建另一个具有不同类型的相同名称的属性。我们可以在<declare-styleable>元素内部定义attr,如果这个attr之前定义过,则会不需要指定format

<resources>
    <attr name="my_attribute" format="boolean" />
    <declare-styleable name="MyCustomView">
        <attr name="my_attribute" />
    </declare-styleable>
</resources>

如果希望重用一个android attr,例如:android:gravity,则可以如下定义

<resources>
  <declare-styleable name="MyCustomView">
    <attr name="android:gravity" />
  </declare-styleable>
</resources>

一个元素有两个xml属性名和格式。name是自定义属性的名字,可用在代码中使用名字调用,例如R.attr.my_attributeR.styleable.CircleImageView_civ_border_width

public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  
  TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);
  
  String str = a.getString(R.styleable.CircleImageView_civ_border_width);
  a.recycle();
}

format属性可以有不同的值,这取决于属性的type

  • reference - 如果引用的是一个资源文件 (例: "@color/my_color", "@layout/my_layout")
  • color
  • boolean
  • dimension
  • float
  • integer
  • string
  • fraction
  • enum - 通常隐式定义
  • flag - 通常隐式定义

可以使用|format设置为多个类型,例:format="reference|color"

format取值类型

refrence:资源类型

<declare-styleable name="CircleImageView">
    <attr name="civ_background" format="reference" />
</declare-styleable>
===>
<CircleImageView
    android:layout_width = "42dip" 
    android:layout_height = "42dip" 
    app:civ_background = "@drawable/R.drawable.home"/>

color: 颜色

<declare-styleable name="CircleImageView">
    <attr name="civ_border_color" format="color" />
</declare-styleable>
===>
<CircleImageView
    android:layout_width = "50dip" 
    android:layout_height = "50dip" 
    app:civ_border_color = "#ff0000"/>

boolean: 布尔

<declare-styleable name="CircleImageView">
    <attr name="civ_border_overlay" format="boolean" />
</declare-styleable>
===>
<CircleImageView
    android:layout_width = "50dip" 
    android:layout_height = "50dip" 
    app:civ_border_overlay = "false"/>

dimension: 尺寸

<declare-styleable name="CircleImageView">
    <attr name="civ_border_width" format="dimension" />
</declare-styleable>
===>
<CircleImageView
    android:layout_width = "50dip" 
    android:layout_height = "50dip" 
    app:civ_border_width = "50dip"/>

float: 浮点值

<declare-styleable name="AlphaAnimation">
    <attr name="fromAlpha" format="float" />
    <attr name="toAlpha" format="float" />
</declare-styleable>
===>
<alpha
    android:duration="100"
    android:fromAlpha="0.0"
    android:toAlpha="1.0" />

integer: 整型值

<declare-styleable name="ProgressBar">
    <attr name="min" format="integer" />
   <attr name="max" format="integer" />
</declare-styleable>
===>
<ProgressBar
    android:min="1"
    android:max="100"/>

string: 字符串

<declare-styleable name="TextView">
   <attr name="text" format="string" />
   <attr name="hint" format="string" />
</declare-styleable>
===>
<TextView
    android:text="Hello, World"
    android:hint="请输入..."/>

fraction: 百分数

<declare-styleable name="RotateDrawable">
  <attr name="pivotX" format="float|fraction" />
  <attr name="pivotY" format="float|fraction" />
</declare-styleable>
===>
<rotate 
    android:pivotX="0.5"
    android:pivotY="50%"/>

enum: 枚举

<declare-styleable name="TextView">
   <attr name="ellipsize">
        <enum name="none" value="0" />
        <enum name="start" value="1" />
        <enum name="middle" value="2" />
        <enum name="end" value="3" />
        <enum name="marquee" value="4" />
   </attr>
</declare-styleable>
===>
<TextView
    android:text="Hello, World"
    android:ellipsize="end"/>

flag: 或运算

<attr name="gravity">
  <flag name="top" value="0x30" />
  <flag name="bottom" value="0x50" />
  <flag name="left" value="0x03" />
  <flag name="right" value="0x05" />
</attr>
<declare-styleable name="TextView">
   <attr name="gravity" />
</declare-styleable>
===>
<TextView
    android:text="Hello, World"
    android:gravity="bottom|right"/>

使用|format设置为多个类型

<declare-styleable name="ImageView">
   <attr name="background" format="reference|color" />
</declare-styleable>
===>
<ImageView
    android:layout_width = "50dip" 
    android:layout_height = "50dip" 
    android:background = "@drawable/R.drawable.icon"/>
<ImageView
    android:layout_width = "50dip" 
    android:layout_height = "50dip" 
    android:background = "#ff0000"/>