Android笔记之View XML属性自定义

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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值