Android自定义View之自定义属性

在我们平时写布局文件的时候会用到很多属性,这是系统帮我们定义好的一些属性,这些属性在\sdk\platforms\android-XX\data\res\valus目录下,这是系统自带的所有属性。如下就是一些常用到的系统自带属性:

因为所有的控件都是View的子类,所以View定义的属性所有的控件都能使用,但是View的子类,如TextView、ImageView定义的属性,就只能他自己使用了。所以如果系统现有的属性不能满足我们的需求,就需要我们来自定义属性了。

 

如何自定义属性

上图中,attr标签后面有带format属性的,有不带format属性的,如果带format属性就是在定义属性,如果不带format属性就是在使用已有的属性,其中name的值就是属性的名字,format是限定当前定义的属性能接受什么值,一共有string、color、demension、integer、enum、reference、float、boolean、fraction、flag这几种类型。举个例子,比如系统已经定义了android:text属性,我们继承View自定义控件(如果是继承TextView自定义的属性,TextView中本身就有这种属性,就不需要再定义了)也需要一个文本的属性,可以有两种方式:

第一种:我们自己定义一个名为text(或者其他名称,属性名称可以随便起)的属性

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

第二种:我们不自己定义属性,只需要在自定义属性中申明,我要使用这个属性(注意加上android命名空间,这样才知道使用的是系统的某个属性)

<declare-styleable name="MyTextView">
  <attr name="android:text"/>    
</declare-styleable>

format属性值类型:

1、reference:参考某一资源ID

属性定义:

<declare-styleable name="MyTextView">
    <attr name="src" format="reference" />
</declare-styleable>

属性使用:

<com.example.customviewattribute.MyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:src="@drawable/ic_launcher_background"/>

2、color:颜色值

属性定义:

<declare-styleable name="MyTextView">
   <attr name="color" format="color"/>
</declare-styleable>

属性使用:

<com.example.customviewattribute.MyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:color="@color/colorAccent"/>

3、boolean:布尔值

属性定义:

<declare-styleable name="MyTextView">
   <attr name="canSelect" format="boolean"/>
</declare-styleable>

属性使用:

<com.example.customviewattribute.MyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:canSelect="@color/colorAccent"/>

4、dimension:尺寸值

属性定义:

<declare-styleable name="MyTextView">
   <attr name="size" format="dimension"/>
</declare-styleable>

属性使用:

<com.example.customviewattribute.MyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:size="@dimen/dp_10"/>

5、float:浮点值

属性定义:

<declare-styleable name="MyTextView">
   <attr name="alpha" format="float"/>
</declare-styleable>

属性使用:

<com.example.customviewattribute.MyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        app:alpha="10.5"/>

6、integer:整型值

属性定义:

<declare-styleable name="MyTextView">
   <attr name="count" format="integer"/>
</declare-styleable>

属性使用:

<com.example.customviewattribute.MyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:count="10"/>

7、string:字符串

属性定义:

<declare-styleable name="MyTextView">
   <attr name="text" format="string"/>
</declare-styleable>

属性使用:

<com.example.customviewattribute.MyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:text="hahahahaha"/>

8、fraction:百分数

属性定义:

<declare-styleable name="MyTextView">
   <attr name="transparency" format="fraction"/>
</declare-styleable>

属性使用:

<com.example.customviewattribute.MyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:alpha="20%"/>

9、enum:枚举值

属性定义:

<declare-styleable name="MyTextView">
   <attr name="orientation">
        <enum name="vertical" value="0" />
        <enum name="horizontal" value="1" />
   </attr>
</declare-styleable>

属性使用:

<com.example.customviewattribute.MyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:orientation="vertical" />

10、flag:位或运算

属性定义:

<declare-styleable name="MyTextView">
    <attr name="gravity">
        <flag name="top" value="0x30"/>
        <flag name="left" value="0x03"/>
        <flag name="bottom" value="0x50"/>
        <flag name="right" value="0x05"/>
    </attr>
</declare-styleable>

属性使用:

<com.example.customviewattribute.MyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:gravity="top|left" />

这10种类型可以组成混合类型,属性定义时指定多种类型值。

属性定义:

<declare-styleable name="MyTextView">
   <attr name="background" format="reference|color"/>
</declare-styleable>

 

在类中获取属性值

在构造方法中获取属性值:

public class MyTextView extends View {


    public MyTextView(Context context) {
        this(context,null);
    }

    public MyTextView(Context context, AttributeSet attrs) {
        this(context, attrs,0);

    }

    public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.MyTextView);

        String text=ta.getString(R.styleable.MyTextView_text);
        int color=ta.getColor(R.styleable.MyTextView_color, Color.BLUE);
        int size=ta.getDimensionPixelSize(R.styleable.MyTextView_size,10);

        //回收TypedArray
        ta.recycle();

        Log.i("rx","text="+text);
        Log.i("rx","color="+color);
        Log.i("rx","size="+size);

    }
}

 

AttributeSet、TypedArray和declare-styleable

AttributeSet:

在上边的构造方法中获取属性值的时候,我们看到AttributeSet和TypedArray两个类,AttributeSet是属性的集合,它的内部就是一个XML解析器,帮我们将布局文件中该控件的所有属性解析出来,并以key-value的键值对形式维护起来。

public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        for (int i = 0; i < attrs.getAttributeCount(); i++) {
            Log.i("rx", "attrName=" + attrs.getAttributeName(i) + 
                    "   attrValue=" + attrs.getAttributeValue(i));
        }
    }

打印的结果是:

rx: attrName=layout_width   attrValue=100.0dip
rx: attrName=layout_height   attrValue=100.0dip
rx: attrName=color   attrValue=@2130968615
rx: attrName=size   attrValue=20.0dip
rx: attrName=text   attrValue=测试数据

我们看到,通过AttributeSet获取属性的值的时候,它会将我们布局文件中的值原原本本的获取出来:比如宽度=100.0dip,如果我们需要使用这个宽度的话,需要把dip去掉,然后转换成整形、color获取到的是一个资源ID,需要我们自己通过ID获取到真正的颜色。

TypedArray:

使用TypedArray,获取到的就是我们真正需要的不需要再做转换的值:

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyTextView">
        <attr name="color" format="color" />
        <attr name="android:layout_width" />
        <attr name="android:layout_height" />
    </declare-styleable>
</resources>

布局文件:

<com.example.customviewattribute.MyTextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        app:color="@color/colorPrimary" />

自定义View:

public class MyTextView extends View {


    public MyTextView(Context context) {
        this(context, null);
    }

    public MyTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);

    }

    public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.MyTextView);
        int color=ta.getColor(R.styleable.MyTextView_color,Color.BLUE);
        float width=ta.getDimension(R.styleable.MyTextView_android_layout_width,200);
        float height=ta.getDimension(R.styleable.MyTextView_android_layout_height,200);

        Log.i("rx","color="+color);
        Log.i("rx","width="+width);
        Log.i("rx","height="+height);
    }
}

输出结果是:

rx: color=-16743049
rx: width=150.0
rx: height=150.0

可以看到,通过TypedArray方式获取的属性,拿到的就是我们想要的值。

declare-styleable:

所有的资源文件在R中都会对应一个整形常量,我们可以通过这个ID值找到资源文件。属性在R中对应的类是public static final class attr,如果我们写了declare-styleable,在R文件中就会生成styleable类,这个类其实就是将每个控件的属性分组,然后记录属性的索引值,而TypedArray正好需要通过此索引值获取属性。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值