您的位置:首页 > 移动开发 > Android开发

Android 自定义属性的理解和使用

2016-07-08 10:41 441 查看

一、引言

有时候Android传统的页面布局不足以满足我们的需求,常常需要自己定义view,通常继承View,然后重写构造方法以及onDraw等函数,再具体实现自己定义的复杂view。我们知道在给控件赋属性时,通常使用的是android系统自带的属性,比如
android:layout_height="wrap_content",除此之外,我们亦可以自己定义属性,这样在使用的时候我们就可以使用形如 testapp:testSize="15sp"的方式了

二、使用步骤

1.在项目文件res/value下面创建一个attrs.xml文件即自定义属性的声明文件,该文件中包含若干个attr集合,例如:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="test">
<attr name="textSize" format="dimension"/>
<attr name="texsColor" format="color"/>
<attr name="type" format="integer"/>
<attr name="background" format="reference"/>
</declare-styleable>
</resources>

其中resource是根标签,可以在里面定义若干个declare-styleable,<declare-styleable name="MyView">中name定义了属性集合的名称,下面可以再自定义多个属性,针对<attr name="testSize" format="dimension"/>来说,其属性的名称为"testSize",format指定了该属性类型为dimension,表示尺寸值。

format还可以指定其他的类型比如;

reference   表示引用,参考某一资源ID

string   表示字符串
color   表示颜色值
dimension   表示尺寸值
boolean   表示布尔值
integer   表示整型值
float   表示浮点值
fraction   表示百分数
enum   表示枚举值

flag   表示位运算

2.在使用到该自定义view的布局文件中键入一行代码,为该自定义属性添加命名空间,名称可以自己定义,在这我定义为testapp,并不要求一定是自定义view的名字,同时使用Eclipse和AS的在此有点区别:



Ecplise:其中com.cx.test为应用程序包名:

xmlns:testapp="http://schemas.android.com/apk/res/com.cx.test"


AS:以前写应用程序包名的方法被AS废弃掉了,直接使用res-auto:

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


接下来就可以在布局文件中使用自定义属性啦:

<com.cx.test.MyView
android:layout_width="100dp"
android:layout_height="100dp"
testapp:textColor="#000000"
testapp:textSize="15sp"
testapp:type="1"
/>




3.在自定义view的代码中引入自定义属性,修改构造函数:

AttributeSet与TypedArray:

构造方法中的有个参数叫做AttributeSet(eg: MyView(Context context, AttributeSet attrs) )这个参数看名字就知道包含的是参数的集合,那么我能不能通过它去获取我的自定义属性呢?首先AttributeSet中的确保存的是该View声明的所有的属性,并且外面的确可以通过它去获取(自定义的)属性,怎么做呢? 

其实看下AttributeSet的方法就明白了,下面看代码:

public class MyView extends View {
    private static String TAG=MyView.class.getSimpleName();
    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        //使用AttributeSet获取属性
        for (int i=0;i<attrs.getAttributeCount();i++){
            Log.e(TAG, "MyView: =name=" + attrs.getAttributeName(i) + "=value=" + attrs.getAttributeValue(i));
        }
    }
}


输出:

E/MyView: MyView: =name=layout_width=value=100.0dip
E/MyView: MyView: =name=layout_height=value=100.0dip
E/MyView: MyView: =name=textSize=value=15.0sp
E/MyView: MyView: =name=textColor=value=#ff000000
E/MyView: MyView: =name=type=value=1
结果果然可以输出自定义view的所有属性,也就是通过AttributeSet可以获得布局文件中定义的所有属性的key和value(还有一些方法,自己去尝试)。

现在关注下一个问题:TypedArray是什么鬼?

我们简单修改下,布局文件中的View的属性:

<com.cx.test.MyView
android:layout_width="100dp"
android:layout_height="100dp"
testapp:textColor="#000000"
        testapp:textSize="@dimen/mysize"
        testapp:type="1"
        testapp:bg="@drawable/aa"
/>
此时输出:
E/MyView: MyView: =name=layout_width=value=100.0dip
E/MyView: MyView: =name=layout_height=value=100.0dip
E/MyView: MyView: =name=textSize=value=@2131230794
E/MyView: MyView: =name=textColor=value=#ff000000
E/MyView: MyView: =name=type=value=1
E/MyView: MyView: =name=bg=value=@2130837504


通过
AttributeSet
获取的值,如果是引用都变成了@+数字的字符串。你说,这玩意你能看懂么?那么你看看最后一行使用TypedArray获取的值,是不是瞬间明白了什么。

TypedArray
其实是用来简化我们的工作的,比如上例,如果布局中的属性的值是引用类型(比如:@dimen/myszie),如果使用
AttributeSet
去获得最终的像素值,那么需要第一步拿到id,第二步再去解析id。而TypedArray正是帮我们简化了这个过程。

下面使用TypedArray:

public class MyView extends View {
private static String TAG=MyView.class.getSimpleName();
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
//使用AttributeSet获取属性
//        for (int i=0;i<attrs.getAttributeCount();i++){
//            Log.e(TAG, "MyView: =name=" + attrs.getAttributeName(i) + "=value=" + attrs.getAttributeValue(i));
//        }
//使用TypedArray获取属性
TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.test);
String textSize=ta.getString(R.styleable.test_textSize);
int type=ta.getInteger(R.styleable.test_type,0);
int color=ta.getColor(R.styleable.test_textColor, 0);
Drawable drawable = ta.getDrawable(R.styleable.test_bg);
Log.e(TAG, "MyView: =textSize=" + textSize + "=type=" + type+"=color="+color+"=drawable="+drawable);
ta.recycle();

}
}
输出结果:

E/MyView: MyView: =textSize=20.0sp=type=1=color=-16777216=drawable=android.graphics.drawable.BitmapDrawable@428d6258
可以看出使用TypedArray也可以获取布局文件中使用引用的属性。

通过比较可以看出我们在View的构造方法中,可以通过
AttributeSet
去获得自定义属性的值,但是比较麻烦,而
TypedArray
可以很方便的便于我们去获取。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: