Android 自定义View 中attr属性 深入解析

版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/xx326664162/article/details/78643153

一、attr和styleable

自定义View,如果想在xml指定参数(例如:改变字体颜色,字体大小),需要声明一个styleable,并在里面自己定义一些attr属性。

attr不依赖于styleable,styleable只是为了方便attr的使用。

不使用styleable

自定义属性完全可以不放到styleable里面,比如直接在resources文件中定义一些属性:

<attr name="custom_attr1" format="string" />
<attr name="custom_attr2" format="string" />

一个attr对应R文件的一个id,使用下面的方式获取属性

int[] custom_attrs = {R.attr.custom_attr1,R.custom_attr2};
TypedArray typedArray = context.obtainStyledAttributes(set,custom_attrs);

使用styleable

定义一个styleable,在R文件里会自动生成一个int[],数组里面的int就是定义在styleable里面attr的id。所以我们在获取属性的时候就可以直接使用styleable数组来获取一系列的属性。

<declare-styleable name="custom_attrs">   
          <attr name="custom_attr1" format="string" />
          <attr name="custom_attr2" format="string" />
</declare-styleable>

获取:

  TypedArray typedArray = context.obtainStyledAttributes(set,R.styleable.custom_attrs);

定义一个declare-styleable,自动提供了一个属性数组,使用这个数组获取属性。此外,我觉得使用declare-styleable的方式有利于把相关的属性组织起来,有一个分组的概念,属性的使用范围更加明确。

二、改变属性值

属性值的改变,有下面五种方式:

1、在xml中设置属性值
2、在xml中设置style
3、在Theme中设置style
4、在Theme中设置属性值
5、自定义view中设置默认style

三、obtainStyledAttributes()获取属性

既然上面设置属性的值,有5个地方,那么获取属性的值,也会有5个地方(见下面蓝色字样),且分优先级。

在前面已经使用了obtainStyledAttributes来获取属性了,现在来看看这个函数的声明吧:

//从xml中获取attrs中属性的值
obtainAttributes(AttributeSet set, int[] attrs); 

//从Theme中获取attrs中属性的值
obtainStyledAttributes(int[] attrs); 

//从资源文件定义的style中读取属性 
obtainStyledAttributes(int resId,int[] attrs); 

//多个数据源
obtainStyledAttributes (AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes);

获取属性,参数主要分为两类:第一,我需要获取哪些属性;第二:我从哪里去获取这些属性(数据源)。

attrs

attrs:int[],每个方法中都有的参数,就是告诉系统需要获取哪些属性。

set

set:表示从xml文件为这个View添加的属性。注意,由LayoutInflater加载进来的布局或者View才有这个属性集。

两种数据源:

  • 使用android:layout_width=”wrap_content”直接指定,1、在xml中设置属性值
  • 通过style=”@style/somestyle”指定的。2、在xml中设置style

defStyleAttr

3、在Theme中设置style

在系统Theme设置style ,修改所有的样式,一般会这么做:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="custom_style">@style/custom_theme</item>
</style>
<style name="custom_theme">
        <item name="custom_color1">#36a39b</item>
        <item name="custom_color2">#36a39b</item>
        <item name="custom_color3">#36a39b</item>
</style>

<attr name="custom_style" format="reference"></attr>

上面代码中的custom_style 是style 名称,custom_theme是style 的内容

public CustomView(Context context, AttributeSet attrs) {
        //defStyleAttr参数的值为 R.attr.custom_style
        this(context, attrs, R.attr.custom_style);
}

public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //调用了obtainStyledAttributes的四参函数
        final TypedArray a = context.obtainStyledAttributes(
                attrs, R.styleable.custom_attrs, defStyleAttr, R.style.default_style);
}

resId=defStyleRes

5、自定义view中设置默认style

resId or defStyleRes:直接从资源文件定义的style中获取属性值。

<style name="default_style">
        <item name="custom_color1">#909304</item>
        <item name="custom_color2">#909304</item>
        <item name="custom_color3">#909304</item>
        <item name="custom_color4">#909304</item>
        <item name="custom_color5">#909304</item>

 </style>
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //调用了obtainStyledAttributes的四参函数
        final TypedArray a = context.obtainStyledAttributes(
                attrs, R.styleable.custom_attrs, defStyleAttr, R.style.default_style);
}

obtainStyledAttributes(int[] attrs);

这个函数并未指定数据源,他是在Theme中获取指定属性的值。4、在Theme中设置属性值

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="custom_color1">#32b430</item>
        <item name="custom_color2">#32b430</item>
        <item name="custom_color3">#32b430</item>
        <item name="custom_color4">#32b430</item>

    </style>

TypedArray

我们看到在获取到属性值之后,都会返回一个TypedArray对象,它又是什么鬼?

TypedArray主要有两个作用,

  • 第一是内部转换attrid和属性值数组的关系;
  • 第二是提供了一些类型的自动转化,比如我们getString时,TypedArray会自动将ResId对应的string从资源文件中读出来。

四、优先级

优先级从高到低:

  1. 在xml中设置属性值
  2. 在xml中设置style
  3. 在Theme中设置style
    • 不为0, 则不使用 自定义view中设置的默认style
    • 为0,使用自定义view中设置的默认style
  4. 在Theme中设置属性值

五、代码

https://github.com/JantHsueh/CustomAttrExmp


参考:深入理解Android 自定义attr Style styleable以及其应用

关注我的公众号,轻松了解和学习更多技术
这里写图片描述

猜你喜欢

转载自blog.csdn.net/xx326664162/article/details/78643153