obtainStyledAttributes深入理解

来源:互联网 发布:数据库概要设计 编辑:程序博客网 时间:2024/06/05 15:39
转自:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=245860

以前一直对自定义style,attr,以及theme一知半解,别人自定义的控件也是拿来就用,昨天耐下心子好好研究了一下,

下面就从TypedArray 入手,来系统的理一下这个知识。

public final TypedArray obtainStyledAttributes (AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)

首先我们使用style的目的就是为了重用这些属性及其值,而在style里我们既可以使用系统定义的attr,也可以使用自定义的attr。如下示:
   

  <style name="test">      <item name="attr1">mio</item>      <item name="android:padding">10dp</item>  </style>


上面的attr1即为自定义的属性,其在attrs.xml中的定义为

    
 <declare-styleable name="begin">          <attr name="attr1" format="string"/>          <attr name="android:text"/>   </declare-styleable> 


自定义的属性不仅要指定名称而且也要指明类型,第二个属性没有指定类型,是因为它使用的是系统自定义的属性。

可能你要问,,既然系统已经有了,为什么我们还要把它放在attrs.xml中呢?

        其实这是为了

一清晰的分组,

二能够根据属性集的名字即(begin)来导出相应的 TypedArray(类型数组,简单来说可以理解为,属性-值的队列),即作为上面函数的一个参数。

当然如果说你没有这个需求,只想在xml中使用,完全可以把   


    <attr name="attr1" format="string"/> 

直接放在<resources>根目录下,同样是可以的。

       这里补充一句,在xml中使用自定义属性时,一定要在根目录,或使用的地方加上 声明

    xmlns:bar="http://schemas.android.com/apk/res-auto" 

        然后在使用该属性的地方加上

<com.handsomedylanapp.MySwitch<span style="white-space:pre"></span>bar:attr1="12345"//一定要加上域名<span style="white-space:pre"></span>android:layout_width="fill_parent"<span style="white-space:pre"></span>android:layout_height="wrap_content"></com.handsomedylanapp.MySwitch>


这里的bar,完全是自定义的,你可以用任意的单词,比如miao,但是声明和使用的域名必须要保持一致。


好了,补充完了一堆背景知识,现在我们来看这个函数。

public final TypedArray obtainStyledAttributes (AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)

首先这个函数是context下的函数,一般在view的构造函数中调用,用于自定义一些style.
如下例。

public MySwitch(Context context, AttributeSet attrs) {           super(context, attrs);           // TODO Auto-generated constructor stub           TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.begin,0, R.style.test);           //这里采用的是xml定义+style备用。           text = a.getText(R.styleable.begin_attr1);// 其实这些值是从0开始enum的,就是index;
           a.recycle();//typedArray是从一个pool中取出的,用完一定要recycle(),回收内存        }

第一个参数是xml文件中的定义的属性集(理解为键值对),

        R.styleable.begin即为要取出typeArray的目标属性(理解为键),上文已述。

        第三个是系统当前theme下默认的属性集(理解为建值对),

        第四个是备用的一个style(理解为键值对)。


这几个参数的优先级如下示:

        1.xml里的显示定义如   bar:attr1="12345"      大于      

        2 xml里的style定义如:android:style=@style/test    大于

        3.当前theme    大于

4.备用Style。

        android系统会按照优先级依次去查找。大家有兴趣可以自己做个实验看一看。



如果大家看过很多国外人开发的代码的话,可能发现,他们不是这么用的,大部分是这么用,原理见上。

<span style="white-space:pre"></span>TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.Switch, R.attr.switchStyle, 0);


我一开始看着也觉着简单,但复现的时候,却出现总是获取不到值的情况,发现还有很多要注意的。

      //首先,在application中把主题设为我们的自定义的主题,已经是自定义的就pass这步。      <application        android:theme="@style/Theme"




     //然后.要在attrs.xml里自定义switchStyle属性     <attr name="switchStyle" format="reference" />
     //最后,在styles.xml中自定义的自定义主题中加入这个自定义的属性来引用我们自定义的style..(有点绕)     <style name="Theme" parent="@android:style/Theme.Light">          <item name="switchStyle">@style/Switch</item>     </style>

注意context.obtainStyledAttributes实际是context.getTheme().obtainStyledAttributes,也就是说它只能从当前theme中以有的style中进行查找,所以采用第二种方案的同学,切记要把该style加入到自定义theme中然后通过R.attr.switchStyle进行引用。



(作者的排版很乱,正理之)

0 0
原创粉丝点击