Android自定义View读取XML属性详解

来源:互联网 发布:mysql存储图片的路径 编辑:程序博客网 时间:2024/05/17 09:09

今天研究了一下自定义View中XML属性的解析。

首先,我们在声明自定义View时,会直接声明构造函数:

public XCustomView(Context context, AttributeSet attrs)

构造函数接受了一个context变量和一个attrs变量,我们使用attrs就可以解析XML属性了。
这里通常使用的方法是声明一个TypedArray变量,通过context.obtainStyledAttributes方法来获取attrs中的属性;实际这里直接使用attrs来解析也是可以的,但会稍麻烦一些。

自定义View的声明

假设我们的自定义View类名是XCustomView,对应的,先声明一些自定义属性:
CustomViewStyleable.xml

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="XCustomView">        <attr name="testAttrFirst" format="integer"/>        <attr name="testAttrSecond" format="string"/>    </declare-styleable></resources>

简单定义两个属性,其值分别为整形和字符串类型。

接下来简单写一个Activity的布局文件,在以前使用eclipse时,在指定我们自定义属性的名字时,需要在xmlns后指定包名;在Android Studio环境下,由于整个项目使用gradle构建,因此包名根据设置可以在编译时产生变化,IDE此时提示我们不要硬编码将包名设置进去,只需要使用特殊字段来标识就可以:

xmlns:custom_name=”http://schemas.android.com/apk/res-auto”

只需要将custom_name替换为我们自定义的名字即可。
整个activity布局是这样的:

<?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    xmlns:xcustom="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context="com.example.customviewstudy.MainActivity">    <com.example.customviewstudy.XCustomView        android:id="@+id/custom_view"        android:layout_width="100dp"        android:layout_height="200dp"        xcustom:testAttrFirst="12345"        xcustom:testAttrSecond="HelloCustomView"/></LinearLayout>

我们为XCustomView控件指定了5个属性,其中有两个是自定义属性。

TypedArray获取方法

接下来,首先来看使用TypedArray的方法:

public class XCustomView extends View {    public static final String TAG = "CustomView-TAG";    public XCustomView(Context context, AttributeSet attrs) {        super(context, attrs);        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.XCustomView);        int testAttrFirstValue = array.getInt(R.styleable.XCustomView_testAttrFirst, 100);        Log.d(TAG, "testAttrFirstValue: " + testAttrFirstValue);        String testAttrSecondValue = array.getString(R.styleable.XCustomView_testAttrSecond);        Log.d(TAG, "testAttrSecondValue: " + testAttrSecondValue);        array.recycle();    }}

使用context.obtainStyledAttributes方法来生成TypedArray。
这个函数接收两个参数:
构造函数中的AttributeSet类型变量 attrs,
int[]型数组,需传入刚才自定义的xml文件对应变量 R.styleable.XCustomView,这里传入其他的数组(如R.styleable.View),不会报任何错误,不过后面也就解析不出自定义属性了。

得到TypedArray变量后,通过一系列get方法就可以获取到相应属性了,例如
int testAttrFirstValue = array.getInt(R.styleable.XCustomView_testAttrFirst, 100);
其中需要自定义属性所对应的R变量R.styleable.XCustomView_testAttrFirst,以及给定一个默认值(100)。
最后不要忘记TypedArray使用后要通过recycle方法回收,否则会引起内存泄漏。
上面代码运行后输出:

D/CustomView-TAG: testAttrFirstValue: 12345
D/CustomView-TAG: testAttrSecondValue: HelloCustomView

AttributeSet获取方法

下面来看看AttributeSet直接获取的方法:

public class XCustomView extends View {    public static final String TAG = "CustomView-TAG";    public XCustomView(Context context, AttributeSet attrs) {        super(context, attrs);        for (int i =0; i < attrs.getAttributeCount(); i++) {            Log.d(TAG, "attrs get No." + i + " attr name: " + attrs.getAttributeName(i) + ", value: " + attrs.getAttributeValue(i));        }        Log.d(TAG, "attrs get first value: " + attrs.getAttributeIntValue("http://schemas.android.com/apk/res-auto", "testAttrFirst", 100));        Log.d(TAG, "attrs get second value: " + attrs.getAttributeValue("http://schemas.android.com/apk/res-auto", "testAttrSecond"));        Log.d(TAG, "attrs count: " + attrs.getAttributeCount());    }}
  1. 通过getAttributeCount方法,就可以获得控件总共的属性数量;
  2. getAttributeName来获取对应index处的属性名称,以sting返回。
  3. attrs.getAttributeValue来获取相应index处属性的值,以string返回。

除了这种遍历的方法,还可以指定获取特定属性。
例如getAttributeIntValue方法,他接受三个参数:

public int getAttributeIntValue(String namespace, String attribute, int defaultValue);

namespace代表自定义属性的命名空间,同xml种的方法,在studio工程中,自定义属性仅需要传入

http://schemas.android.com/apk/res-auto;

attribute是对应属性名称,在这里是我们声明的testAttrFirst;
defaultValue为默认值,当没有获取到xml中的数值时,就返回这个默认值。

上面的代码运行后输出:

D/CustomView-TAG: attrs get No.0 attr name: id, value: @2131492944
D/CustomView-TAG: attrs get No.1 attr name: layout_width, value: 100.0dip
D/CustomView-TAG: attrs get No.2 attr name: layout_height, value: 200.0dip
D/CustomView-TAG: attrs get No.3 attr name: testAttrFirst, value: 12345
D/CustomView-TAG: attrs get No.4 attr name: testAttrSecond, value: HelloCustomView
D/CustomView-TAG: attrs get first value: 12345
D/CustomView-TAG: attrs get second value: HelloCustomView
D/CustomView-TAG: attrs count: 5

总结

1.使用TypedArray获取,需要AttributeSet与int[]两个参数,int[]数组需要与当前自定义View类型匹配,否则就无法解析出自定义属性。
使用TypedArray后切记不要忘记调用recycle回收。
2.使用AttributeSet获取需要提供自定义属性的命名空间,在studio工程中,只需要传入特殊值http://schemas.android.com/apk/res-auto即可。
获取具体属性及取值直接调用AttributeSet的接口即可。

0 0
原创粉丝点击