Android笔记之View XML属性自定义

来源:互联网 发布:o2olr软件下载 编辑:程序博客网 时间:2024/05/21 10:40

1, 简介

  一般来说,我们进行自定义View,但除非使用Android 原生的 XML属性,我们想添加自定义的XML属性来扩展自定义View的复用性。

2, 实现流程

  1. 编写 values/attrs.xml, 在其中进行编译 styleable 和 item 等标签元素;
  2. 自定义一个CustomView类(继承View或者其子类);
  3. 在布局文件中使用CustomView进行布局并使用自定义的属性(注:xmlns(XML命名空间));
  4. 在 CustomView的构造方法中通过 TypedArray获取;

3, 实现Damo

a) values/attrs.xml:

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="steven">        <attr name="text" format="string" />        <attr name="testAttr" format="integer" />    </declare-styleable></resources>

b) 布局文件 main.xml

<?xml version="1.0" encoding="utf-8"?><!--com.example.yufen.learnapplication为--><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:zyf="http://schemas.android.com/apk/res/com.example.yufen.learnapplication"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent">    <!--注: xmlns:zyf="http... 为 XML命名空间,必须添加;com.example.yufen.learnapplication则为该应用程序的Package Name;但Android Studio推荐统一使用:  xmlns:zyf="http://schemas.android.com/apk/res-auto"-->    <com.example.yufen.learnapplication.MyTextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        zyf:testAttr="520"        zyf:text="HelloWord"/></LinearLayout>

c) 自定义View:

package com.example.yufen.learnapplication;import android.content.Context;import android.content.res.TypedArray;import android.util.AttributeSet;import android.widget.TextView;/** * Created by Yufen on 2016/6/6. */public class MyTextView extends TextView {    public MyTextView(Context context) {        super(context);    }    public MyTextView(Context context, AttributeSet attrs) {        super(context, attrs);        //将steven的styleable的属性的值进行统一读取出来        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.steven);        //steven_testAttr为 styleable的名字 + _  + 自定义属性的名字        int textAttr = ta.getInteger(R.styleable.steven_testAttr, -1);        String text = ta.getString(R.styleable.steven_text);        setText("text = " + text + " , textAttr = " + textAttr);         //释放回收        ta.recycle();    }    public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }}

4, AttributeSet与TypedArray

  AttributeSet中保存的是该View声明的所有的属性,并且外面的确可以通过它去获取(自定义的)属性;

int count = attrs.getAttributeCount();        for (int i = 0; i < count; i++) {            String attrName = attrs.getAttributeName(i);            String attrVal = attrs.getAttributeValue(i);            Log.e("yufen", "attrName = " + attrName + " , attrVal = " + attrVal);        }

  但如果 布局是这样定义时(android:layout_height=”@dimen/dp200”), AttributeSet中获取的值 为 @2131165235, 我们则需要下面的才能读取其值:

int widthDimensionId =  attrs.getAttributeResourceValue(0, -1);Log.e("yufen", "layout_width="+getResources().getDimension(widthDimensionId));

而我们可直接通过 TypedArray来简捷读取内容:

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.steven);int textAttr = ta.getInteger(R.styleable.steven_testAttr, -1);String text = ta.getString(R.styleable.steven_text);

总结:AttributeSet 的作用就是在控件进行初始化的时候,解析布局文件中该控件的属性(key eg:background)与该值(value eg:@drawable/icon)的信息封装在AttributeSet中,传递给该控件(View)的构造函数。对于非Android自带的属性,在View类中处理时是无法识别的,因此需要我们自己解析。所以这就要用到另外一个类TypedArray。在AttributeSet中我们有属性名称,有属性值,但是控件如何知道哪个属性代表什么意思呢?这个工作就由TypedArray来做了。TypedArray对象封装了/values/attrs.xml中的styleable里定义的每个属性的类型信息,通过TypedArray我们就可以知道AttributeSet中封装的值到底是干什么的了,从而可以对这些数据进行应用。

5, Declare-styleable用法

  1) Declare-styleable用法详解请直接参考: Android 自定义属性用法详解
  2) Damo:
a) attrs.xml

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="steven">        <!--字符串-->        <attr name="text" format="string" />        <!--整型值-->        <attr name="testAttr" format="integer" />        <!--参考某一资源ID-->        <attr name="my_backgroud" format="reference" />        <!--颜色值-->        <attr name="my_textColor" format="color" />        <!--布尔值-->        <attr name="my_clickable" format="boolean" />        <attr name="my_width" format="dimension" />        <!--浮点值-->        <attr name="my_alpha" format="float" />        <!--百分数-->        <attr name="my_pivotX" format="fraction" />        <!--枚举值-->        <attr name="my_orientation" >            <enum name="horizontal" value="0" />            <enum name="vertical" value="1"/>        </attr>        <!--位或运算-->        <attr name="my_windowSoftInputMode">            <flag name = "stateUnspecified" value = "0" />            <flag name = "stateUnchanged" value = "1" />            <flag name = "stateHidden" value = "2" />            <flag name = "stateAlwaysHidden" value = "3" />            <flag name = "stateVisible" value = "4" />            <flag name = "stateAlwaysVisible" value = "5" />            <flag name = "adjustUnspecified" value = "0x00" />            <flag name = "adjustResize" value = "0x10" />            <flag name = "adjustPan" value = "0x20" />            <flag name = "adjustNothing" value = "0x30" />        </attr>    </declare-styleable></resources>

b) main.xml

<?xml version="1.0" encoding="utf-8"?><!--com.example.samsung.learnapplication为--><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:zyf="http://schemas.android.com/apk/res-auto"    android:orientation="vertical" android:layout_width="match_parent"    android:layout_height="match_parent">    <!---->    <com.example.yufen.learnapplication.MyTextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        zyf:text="HelloWord"        zyf:testAttr="520"        zyf:my_backgroud="@drawable/send_music_thumb"        zyf:my_textColor="#F5F5F5"        zyf:my_clickable="true"        zyf:my_width="200dp"        zyf:my_alpha="0.9"        zyf:my_pivotX="65%"        zyf:my_orientation="horizontal"        zyf:my_windowSoftInputMode="stateAlwaysHidden|stateAlwaysVisible|adjustNothing"        /></LinearLayout>

c) 自定义View 解析自定义属性值 :

package com.example.yufen.learnapplication;import android.content.Context;import android.content.res.TypedArray;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.util.Log;import android.widget.TextView;/** * Created by Yufen Zhi on 2016/6/6. */public class MyTextView extends TextView {    public MyTextView(Context context) {        super(context);    }    public MyTextView(Context context, AttributeSet attrs) {        super(context, attrs);        //        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.steven);        //steven_testAttr为 styleable的名字 + _  + 自定义属性的名字        int textAttr = ta.getInteger(R.styleable.steven_testAttr, -1);        String text = ta.getString(R.styleable.steven_text);        Drawable drawable = ta.getDrawable(R.styleable.steven_my_backgroud);        int color  = ta.getColor(R.styleable.steven_my_textColor, 0xFFFFF);        boolean clickable = ta.getBoolean(R.styleable.steven_my_clickable, false);        float  width = ta.getDimension(R.styleable.steven_my_width, 0);        float alpha = ta.getFloat(R.styleable.steven_my_alpha, 0.0f);        float pivotX = ta.getFraction(R.styleable.steven_my_pivotX, 1, 1, 0);        int orientation = ta.getInteger(R.styleable.steven_my_orientation, -1);        int windowSoftInputMode = ta.getInteger(R.styleable.steven_my_windowSoftInputMode, 0);        String windowSoftInputMode_string = ta.getString(R.styleable.steven_my_windowSoftInputMode);        //释放回收        ta.recycle();        Log.d("yufen","text = " + text + ", textAttr = " + textAttr + ", drawable = " + drawable + ", color= " + color +  ", clickable = " + clickable + ", width = " + width  + ",alpha = " + alpha + ", pivotX = " + pivotX  + ", orientation = " + orientation + ", windowSoftInputMode = " + windowSoftInputMode + ", windowSoftInputMode_string = " + windowSoftInputMode_string);    }}

d) 得到的结果为:

06-07 13:49:55.561 21946-21946/? D/yufen: text = HelloWord, textAttr = 520, drawable = android.graphics.drawable.BitmapDrawable@301ef41, color= -657931, clickable = true, width = 700.0,alpha = 0.9, pivotX = 0.65, orientation = 0, windowSoftInputMode = 55, windowSoftInputMode_string = 0x37

特别要注意: 属性定义时可以指定多种类型值。

<declare-styleable name = "名称">    <attr name = "background" format = "reference|color" /></declare-styleable>
0 0