View的探讨(一):自定义属性(attr),XML开始到java

转载请标明出处:http://blog.csdn.net/hioor/article/details/50907396

一、概述

自定义属性(attribute)是自定义View中不可或缺的一部分,在xml中输入的数据直接成为控件(View)的一部分,确实可以大大简化布局时对自定义控件的控制。

二、从xml开始讲View和ViewGroup的属性

1、从自定义属性开始了解 attr.xml 属性定义

在xml中,不论是View和ViewGroup都有很多属性,如layout_width,layout_heighth之类的,当然,这些都是系统自带的,而且,有一些属性,如android:gravity 是有固定的一些值的,如“center”、“end”等等。当然,归根结底,这些选项的实现方式,都是通过java代码实现的!但是,这个数值是怎么走过去的呢? 这里靠的是一个Values中的一个指定的xml文件 ——attr.xml ,也就是属性(attribute)文件的意思。
如系统中自带的一个属性:background

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

其中
“名称”指的是控件(View)的名称
“background” 也就是控件中的属性的名字
“reference”指的是这个“background”属性的格式
这里可以用代码中的逻辑方式这么理解

项目代码中的形式attr中的形式
属性类型intreference
属性名称numberbackground
属性值10@drawable/icon

和java中的有限的几个属性类型一样,attr中的属性类型也是有限的,如下

编号属性名称属性值举例名称例子
1reference:引用资源ID@mipmap/ic_launcher……background
2color:颜色值112233、@color/primary_colortextcolor(TextView)
3dimension:尺寸值10dp、10px……layout_width
4boolean:布尔值true、falselayout_centerInParent(RelativeLayout)
5float:浮点值10.0fromAlpha(anim.xml)
6integer:整型值1max(ProgressBar)
7string:字符串“helloworld”text(TextView)
8fraction:百分数“helloworld”text(TextView)
9flag:位或运算center、end、rightgravity(FrameLayout)
10enum:枚举值。verticalorientation

ps1:enum属性表示为在enum中的数个值选择一个,表示“非1即2”;flag属性表示为在flag中的数值则
是可以多个并列的,表示“1”、“2”、或者“1 | 2”
ps2:多个属性是可以一起用的,譬如:background

            <declare-styleable name = "名称">
                   <attr name = "background" format = "reference|color" />
            </declare-styleable>
2、自定义属性在xml中的使用

首先先创建一个attr.xml文件,如果有的话就不用创建了。然后在文件中加入如下代码:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="DiyView">
        <attr name="diycolor" format="color"/>
    </declare-styleable>
</resources>

于是,这个时候,就可以在xml中使用DiyView的自定义控件的 diycolor属性了?no!
因为我们还有个准备活动没有做,就是生成一个DiyView的java代码,才能表示“我们确实有了一个叫做DiyView的控件”,然后才能在xml中使用这么一个自定义的View
那么,首先,在src文件中创建一个DiyView.java,并继承View

public class DiyView extends View {
    public DiyView(Context context) {
        super(context);
    }

    public DiyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public DiyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
}

其中有三个必须要实现的构造函数,我们暂时先不管java部分的代码,因为这是个极大的坑,需要我们整整花好久去分析,所以,只能先去xml中感受一下自定义属性要怎么玩~

以下是我的activity_main.xml中的代码

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="resarch.com.datatimeselector.MainActivity">
    <resarch.com.datatimeselector.DiyView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />


</RelativeLayout>

然而,此时出现了这么一个问题:
这里写图片描述
Rendering Problems
The DiyView custom view has been edited more recently than the last build: Build the project.
这个时候,点击build就好了,这意味着你重新建立了xml对DiyView.java代码的联系,从现在的角度讲,xml就能够使用你的自定义View了。
然后在DiyView中加入自定义属性“diycolor”,然后随便选一种颜色就好了,代码如下

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context="resarch.com.datatimeselector.MainActivity">
    <resarch.com.datatimeselector.DiyView
        android:layout_width="200dp"
        android:layout_height="200dp"
        app:diycolor="#f90"/>
</RelativeLayout>

ps1:diycolor的前面的代码不是android,而是app
ps2:在RelativLayout里面多了一行xmlns:app=”http://schemas.android.com/apk/res-auto”表示这个app系列的属性都引用自自定义的文件attr.xml中,虽然看起来是res-auto。
当然,如果把xmlns:app……中的app改成test,那么,只要把后面的app:diycolor……里的app也改成test就好了

我相信,这个时候你看到的画面和我看到的画面一样,什么变化都没发生……还不如原来自动生成的“hello world”,比如我这边的图就是这样的:
这里写图片描述

其实嘛,是这样的,这个属性值是传到java代码里了,但是,我们在java代码里什么事儿都没做呢……空空如也,所以,不管在什么类型的自定义的属性,里面放了什么数据,其实都没什么效果。这个时候我们需要返回java代码中,把它实现掉

三、java代码中的自定义属性

我们终于走到了这一步,而我们需要做的,就是先把这个自定义属性从xml中拿过来,但是三个构造函数,哪个才是有用的?无需多言,直接使用杀手锏:三合一,代码如下:

public class DiyView extends View {
    public DiyView(Context context) {
        this(context,null);
    }

    public DiyView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public DiyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
}

ps:就是把前两个构造函数的最终都引到第三个构造函数中,就是super改成this,然后再加上需要的参数向下一个构造函数走(如果你问我这种编码方式是哪里来的?我只能说:看android系统定义的某些View的源码)

然后,使用一个叫做TypeArray的类来接收这个自定义属性的数

    public DiyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.DiyView);
        int color = a.getColor(R.styleable.DiyView_diycolor,Color.RED);
        a.recycle();
    }

TypeArray接收了attr里定义在 name=DiyView中的所有的自定义属性,当然,这么多的数据不可能用一个指针来搞定,我们只能从这个集合中取出一部分来使用
所以,按照这种尿性,这个 对象 a 中,可以get到我们之前讲过的10种属性的数据,当然
a.getColor(R.sytleable.DiyView_diycolor,Color.RED),为了以防报错(也就是属性没给值的情况),这个地方需要弄一个默认值 ,如这里的参数“Color.RED”。
a.recycle(),“让TypeArray回到循环里,等待下一次的调用”是源码中的解释,“但是用过这个方法的方法不能再次使用它了”,这说明还有其他的方法会用到这个TypeArray,但是,AttributeSet的值不是我们自己创建(new)出来的,也就说,这个数值会交给下一个View去使用

接下来,看看我们这个定义的属性是否真的传入了java文件中,我们可以直接加入如下一行代码:

 setBackgroundColor(color);

现在我们回到刚才的xml中去看看是否有效果:
(这时候会出现一段熟悉的字样,没错,我们这个时候需要点击蓝色字:build)
这里写图片描述
ps1:这里,f90本来就是屎黄色……
ps2:代码里的setBackgroundColor()方法就是设置这个view的背景颜色

四、小结

  • 自定义属性的步骤:
    1.创建attrs.xml文件
    2.在xml文件中使用
    3.在java文件中获取并使用

  • 当然,讲到目前为止,也只是讲到关于View的知识的一个小点。当然,按照这个attrs.xml的推论往回走,我们可以知道,其实在android,这些控件的xml属性都是在某个系统的attrs.xml中定义过的,然后再在对应的View中进行接收,然后进行处理!下一节会开始讲View在java文件中的处理!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值