Android自定义属性详细剖析(一)

Android自定义属性详细剖析(一)

标签: 自定义ViewTypedArray自定义属性formatTintTyped
  278人阅读  评论(1)  收藏  举报
  分类:

目录(?)[+]

转载请注明出处: 
http://blog.csdn.net/qq347198688/article/details/52665975 
本文出自【何嘉龙的博客

1. 引言

对于自定义属性,我相信大家都接触过,使用过。但是可能对自定义属性存有一些疑问,比如说:

  • 为什么要用到自定义属性?

  • 为什么在xml文件中要用到自定义的命名空间?

  • TintTypedArray与TypedArray有什么不同?

  • format有什么用?可以不加么?

让我们带着这些问题,来进行这篇博客的学习。

2. 常见的例子

进行学习的最好方式,就是有例子作为参考,而不是只是单纯给你灌输理论知识,这样只会苦涩难懂,让新手畏惧不前。

  • 在value目录下新建一个attrs.xml文件如下:

这里写图片描述

  • 接着在attrs.xml文件中,写入自定义声明的属性:
<?xml version="1.0" encoding="utf-8"?>
<resources>

   <declare-styleable name="test">
       <attr name="text" format="string"/>
       <attr name="testAttr" format="integer"/>
   </declare-styleable>

</resources>
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 自定义一个View类
package com.example.attrtest;

import android.content.Context;
import android.support.v7.widget.TintTypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

/**
 * Created by dragonhaw on 2016/9/26.
 */
public class MyTextView extends View {

    private static final String TAG = MyTextView.class.getSimpleName();

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

        TintTypedArray typedArray = TintTypedArray.obtainStyledAttributes(context, attrs, R.styleable.test, defStyleAttr, 0);

        String text = typedArray.getString(R.styleable.test_text);
        int testAttr = typedArray.getInteger(R.styleable.test_testAttr, -1);

        Log.e(TAG, "text = " + text + ", testAttr = " + testAttr);

        typedArray.recycle();
    }
}

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 在布局文件中使用
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <com.example.attrtest.MyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:text="Hello World!"
        app:testAttr="520"/>
</LinearLayout>

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

好了,我们的自定义属性写好了,而且还放在自定义布局中使用了,那这次应该可以看到结果了吧。让我们来运行一下: 
这里写图片描述

咦?好像报错了。让我们来看一下这个错误是什么?

这里写图片描述

大概意思就是, 加载我们的这个自定义View出错。我找了很久才找出解决方法,解决方法就是在自定义View里面加入这几行代码:

public MyTextView(Context context) {
       this(context, null);
   }

public MyTextView(Context context, AttributeSet attrs) {
       this(context, attrs, 0);
   }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

至于出错的原因呢?我推断是当我们在自定义布局中写入我们的自定义View时,所用到的构造函数是带有两个参数的。所以,大家为了防止以后出现莫名其妙而又很难找的错误,最好把那几个构造方法都写出来。

好了,我们把错误已经找出来了,那让我们再继续运行一下: 
这里写图片描述

控制台已经帮我们把结果打印出来了。再让我们看一下,那个小程序有没有把那些结果显示出来:

这里写图片描述

嗯?怎么什么都没有?哈哈,其实这才是正常的,因为你根本都没有在自定义View里面去调用onMesure(),onDraw方法,具体的请参考我转载的自定义View文章系列。咦?我们好像没有定义test_text、test_testAttr这两个item吧?但是又好像很眼熟。

这里写图片描述

其实,正如你们脑海里想的那样,代码中自定义属性名称就是这样的,”_”前面的是数组名test,后面是自定义属性名。至于declare-styleable 在Android自定义属性详细剖析(二)中剖析。

3. 解决疑问

在通过一个示例之后,再来跟大家一起解决前面提出的问题。

  • 自定义属性的基本流程

我们现在attrs.xml文件中声明我们所需要的自定义属性,然后在布局文件中通过命名空间找到我们的自定义属性,接着再在布局文件中使用,然后Java代码中通过obtainStyledAttributes()方法将布局文件中的自定义属性的值给传进来,进行后续操作。基本流程就是这样了。

  • 为什么要使用自定义属性?

自定义属性,可以让我们直接在布局文件中,使用自己定义的属性,来完成需求。使用过开源框架的同学们应该都知道,我们在使用开源框架时,在布局文件中一般都要加上自己的自定义属性,因为这些属性系统没给我们,是我们自己定义的,来完成很多需求的。可能有同学就有疑问了,那为什么我们不直接在代码中完成需求呢?这个问题很好,其实这体现了面向对象的特性——封装性,你要用一个开源框架时,你都不需要去了解代码内部的结构,只需要在自定义布局中加入自定义属性,不是很简单么?

  • 为什么在xml文件中要用到自定义的命名空间?

先让我们来看到自定义命名空间的格式,xmlns:app=”http://schemas.Android.com/apk/res-auto”或者xmlns:app=”http://schemas.android.com/apk/res/com.example.attrtest”,这两个其实是一样的,但是我推荐使用第一个,IDE会自动帮你寻找到项目中的所有自定义属性。所以,要用到自定义的命名空间就是为了帮你去找你自定义的属性。

  • TintTypedArray与TypedArray有什么不同?

这里写图片描述 
可以看到,官方的解释是,TintTypedArray跟TypedArray提供一样的API,所以这两个随便使用哪一个都一样,不需要纠结。

  • format有什么用?可以不加么?

这里写图片描述 
这个是不加后的结果,直接报错。所以format是必须要加的。如果类型都不知道,我们怎么指定自定义属性的值。 
format可以理解为类型, fomat的属性自己定义 根据自己的需要来选择string , integer , dimension , reference , color , enum……

reference:参考指定Theme中资源ID。 
dimension:尺寸值 
float:浮点型 
boolean:布尔值 
integer:整型 
string:字符串 
fraction:百分数 
flag:位或运算 
Color:颜色 
enum:枚举

好啦,自定义属性的第一部分算是讲解完了,如果感兴趣的同学,可以接着看Android自定义属性详细剖析(二)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值