TypedArray相信大家都不陌生,他用于android自定义View中对自定义属性的解析。他的方便之处在于可以直接将例如@drawable/test_drawable这样的图片直接解析成一个Drawable对象,又可以将10dp这样的单位,在代码中直接拿到换算好的px值,方便之处不言而喻。
ok,现在问题来了,如果我只想用一个xml文件作为我一个模块的配置文件,又不想自己去pull解析xml,去解析哪些dp,reference的字符串,该怎么办呢?
废话结束。
首先在values文件夹下创建attrs.xml文件用来编写约束的描述
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="test_attrs"> <attr name="key" format="string" /> <attr name="vercode" format="integer" /> <attr name="background" format="reference" /> <attr name="height" format="dimension" /> <attr name="width" format="dimension" /> </declare-styleable> </resources>
<?xml version="1.0" encoding="utf-8"?> <resource xmlns:aaa="http://schemas.android.com/apk/res/com.example.test1"> <test aaa:key="key_test" aaa:vercode="1002" aaa:background="@drawable/bubble" aaa:height="100dp" aaa:width="200dp" ></test> </resource>
最后就可以在代码中获取这些数据了
public static void parse(Context context, int resourceId){ TypedArray typedArray = getTypedArrayFromResource(context, resourceId, R.styleable.guide, "test"); if(typedArray == null){ return null; } String key = typedArray.getString(R.styleable.test_attrs_key); int vercode = typedArray.getInteger(R.styleable.test_attrs_vercode, 0); Drawable background = typedArray.getDrawable(R.styleable.<span style="font-family: Arial, Helvetica, sans-serif;">test_attrs_background</span><span style="font-family: Arial, Helvetica, sans-serif;">);</span> int height = typedArray.getInteger(R.styleable.test_attrs_height, 0); int width = typedArray.getInteger(R.styleable.test_attrs_width, 0); if(typedArray != null){ typedArray.recycle(); } //TODO do something you want } /** * 通过xml资源文件、其对应的attrs约束文件,获取对应TypedArray</br> * <b>记得用完要释放。</b> * @param context * @param resourceId xml资源id * @param attributeSchema attrs约束定义文件id * @param tagName 需要解析的标签名称 * @return */ @SuppressLint("Recycle") private static TypedArray getTypedArrayFromResource(Context context, int resourceId, int[] attributeSchema, String tagName){ TypedArray typedArray = null; try { if(context == null){ throw new Exception("Context is null in GuiderFactory, cannot fetch TypedArray."); } Resources resource = context.getResources(); if(resource == null){ throw new Exception("Resource is null in GuiderFactory, cannot fetch TypedArray."); }
XmlResourceParser parser = resource.getLayout(resourceId); if(parser == null){ throw new Exception("Parser is null in GuiderFactory, cannot fetch TypedArray."); } AttributeSet attributeSet = null; int state = 0; do { if (state == XmlPullParser.START_TAG && parser.getName().equals(tagName)) { attributeSet = Xml.asAttributeSet(parser); break; } } while(state != XmlPullParser.END_DOCUMENT); if(attributeSet == null){ throw new Exception("AtrributeSet is null in GuiderFactory, cannot fetch TypedArray."); } typedArray = context.obtainStyledAttributes(attributeSet, attributeSchema); }catch (Exception e) { e.printStackTrace(); } return typedArray; }
其实就是将没用的标签过滤掉没用的标签,拿到想要的标签对象。然后生成 AttributeSet, 就可以像在自定义view的构造方法中那样obtain一个TypedArray了。至于其中源码的分析以后有时间再写。最后把attrs可以定义的几种format写一下。
reference 资源引用
string 字符串
color 颜色值,可以直接获取到Color
boolean 布尔值
demension 像素值,自动获取本机的对应demention并且换算为px
float 浮点
integer 整型
fraction 百分数,这个说一下,用在animation的定义上,rotateanimation中的属性pivotX="50%"
enum 枚举。写法为
<declare-styleable name="名称"> <attr name="orientation"> <enum name="horizontal" value="0" /> <enum name="vertical" value="1" /> </attr> </declare-styleable>
flag 位或运算。其实就是枚举是单选,位或运算可以是多选。写法如下
<declare-styleable name="名称"> <attr name="windowSoftInputMode"> <flag name = "stateUnspecified" value = "1" /> <flag name = "stateUnchanged" value = "2" />
<pre name="code" class="html"><span style="white-space:pre"> </span> <flag name = "stateHiden" value = "4" />/**.......*/ </declare-styleable>