android 自定义控件 使用declare-styleable进行配置属性(源码角度)

http://blog.csdn.net/vipzjyno1/article/details/23696537

最近在模仿今日头条,发现它的很多属性都是通过自定义控件并设定相关的配置属性进行配置,于是便查询了解了下declare-styleable,下面我把自己的使用感受和如何使用进行说明下。

declare-styleable:declare-styleable是给自定义控件添加自定义属性用的。

官方的相关内部控件的配置属性文档:http://developer.android.com/reference/android/R.styleable.html

如果不知道如何查看源码:点击这里

起初,在自定义控件的时候,会要求构造3个方法中的一个或多个,好比我自定义的控件PersonView,

[java] view
plain
copy

  1. public PersonView(Context context) {  
  2.         super(context);  
  3.         // TODO Auto-generated constructor stub  
  4.     }  
  5.   
  6.     public PersonView(Context context, AttributeSet attrs, int defStyle) {  
  7.         super(context, attrs, defStyle);  
  8.         // TODO Auto-generated constructor stub  
  9.     }  
  10.   
  11.     public PersonView(Context context, AttributeSet attrs) {  
  12.         super(context, attrs);  
  13. }  

其中的AttributeSet attrs一般都没给它配置和使用,所以不知道这个东西到底怎么用,后来查看源码发现,这个配置在默认情况下使用的是系统自己的默认配置,一旦你直接设定了它的属性,默认属性就会被你的赋值所替代。

下面我们拿TextView的源码看看AttributeSet是如何进行操作的。

初始化时候,在布局文件中写android:text="拉拉";


初始化TextView的时候,它的类中的属性都会初始化;

接着往下看,你可以看到以下代码:

[java] view
plain
copy

  1. TypedArray a = theme.obtainStyledAttributes(  
  2.             attrs, com.android.internal.R.styleable.TextViewAppearance, defStyle, 0);  
  3. TypedArray appearance = null;  
  4. int ap = a.getResourceId(  
  5.         com.android.internal.R.styleable.TextViewAppearance_textAppearance, -1);  
  6. a.recycle();  
  7. if (ap != -1) {  
  8.     appearance = theme.obtainStyledAttributes(  
  9.             ap, com.android.internal.R.styleable.TextAppearance);  

这个就是系统在默认的资源文件R.styleable中去获取相关的配置。

如果appearance不为空,它就会去寻找获取相关属性,接着往下看。

此时的text = "";     就是准备输出的字符串初始化。

之后它便会查找你布局文件XML中是否设定给了它text属性值

之前我们设定过android:text="拉拉";  所以它便会得到相关的赋值,之后调用

[java] view
plain
copy

  1. <span style="font-size:18px;"> setText(text, bufferType);  
  2.  if (hint != null) setHint(hint);  
  3. </span>  

输出该字符串。当资源检查赋值完毕后,调用a.recycle();释放。
同理也可以发现,像hint,textcolor这类属性都是这么初始化赋值的。


思路:

自定义控件并且自定义属性的情况下,你可以通过这样去获取判断是否配置了相关的属性,并进行赋值操作。


从源码那边我们大体知道了一个控件的属性配置和初始化流程,下面就让我们按照这个思路去自己学习下如何自定义配置。


下面我要写一个继承了TextView的PersonView类,给它设定属性配置,之后实现属性的显示。

1.首先,先写attrs.xml

在res-vlaues文件夹下创建资源文件attrs.xml或则自定义一个资源文件xx.xml,都可以。

之后在里面配置declare-styleable ,name为PersonAttr

[html] view
plain
copy

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <declare-styleable name="PersonAttr">  
  4.         <attr name="name" format="reference" />  
  5.         <attr name="sex" format="reference" />  
  6.         <attr name="age" format="integer" />  
  7.         <attr name="weight">  
  8.             <flag name="fat" value="2" />  
  9.             <flag name="mid" value="1" />  
  10.             <flag name="thin" value="0" />  
  11.         </attr>  
  12.         <attr name="adult" format="boolean" />  
  13.         <attr name="textSize" format="dimension" />  
  14.     </declare-styleable>  
  15. </resources>  

我这里设置了姓名name,性别sex,年龄age,以及特征属性weight(fat,mid,thin内部的3个属性及对应的属性值),还有是否成年adult,和TextView的字体大小textView。

可能这里有人会问,format是什么,里面的单词代表的又是什么意思。

format就是格式,里面的就是这个属性对应的格式,下面列出来大致的格式有:

1. reference:参考某一资源ID,以此类推

(1)属性定义:

<declare-styleable name = "名称">

<attr name = "background" format = "reference" />

</declare-styleable>

(2)属性使用:

<ImageView

android:layout_width = "42dip"

android:layout_height = "42dip"

android:background = "@drawable/图片ID"

/>

2. color:颜色值

<declare-styleable name = "名称">

<attr name = "textColor" format = "color" />

</declare-styleable>

3. boolean:布尔值

<declare-styleable name = "名称">

<attr name = "focusable" format = "boolean" />

</declare-styleable>

4. dimension:尺寸值。注意,这里如果是dp那就会做像素转换

<declare-styleable name = "名称">

<attr name = "layout_width" format = "dimension" />

</declare-styleable>

5. float:浮点值。

6. integer:整型值。

7. string:字符串

8. fraction:百分数。

9. enum:枚举值

10. flag:是自己定义的,类似于 android:gravity="top",就是里面对应了自己的属性值。

11. reference|color:颜色的资源文件。
12.reference|boolean:布尔值的资源文件

注意://由于reference是从资源文件中获取:所以在XML文件中写这个属性的时候必须 personattr:name="@string/app_name"这种格式,否则会出错

2.设置好属性文件后,在使用的布局中写相关配置:

[html] view
plain
copy

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:personattr="http://schemas.android.com/apk/res/com.example.declare_styleable"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent" >  
  5.   
  6.     <com.example.declare_styleable.PersonView  
  7.         android:layout_width="wrap_content"  
  8.         android:layout_height="wrap_content"  
  9.         personattr:name="@string/person_name"   
  10.         personattr:weight ="fat"  
  11.         personattr:adult ="false"  
  12.         personattr:textSize="@dimen/text_size"/>  
  13.   
  14. </RelativeLayout>  

这里要先应用这个attr:

[html] view
plain
copy

  1. xmlns:personattr="http://schemas.android.com/apk/res/com.example.declare_styleable"  

对应结构是:

[java] view
plain
copy

  1. xmlns:你自己定义的名称="http://schemas.android.com/apk/res/你程序的package包名"    (我这是com.example.declare_styleable)  

包名是配置文件中   package="com.example.declare_styleable" 这样格式的

之后在布局中自定义的类中设相关属性:

你自己定义的名称:你设的属性 ="属性值";

3.最后在自定义控件的构造方法中获取你配置的属性值:

[java] view
plain
copy

  1. public class PersonView extends TextView {  
  2.     public PersonView(Context context) {  
  3.         super(context);  
  4.         // TODO Auto-generated constructor stub  
  5.     }  
  6.   
  7.     public PersonView(Context context, AttributeSet attrs, int defStyle) {  
  8.         super(context, attrs, defStyle);  
  9.         // TODO Auto-generated constructor stub  
  10.     }  
  11.   
  12.     public PersonView(Context context, AttributeSet attrs) {  
  13.         super(context, attrs);  
  14.         // TODO Auto-generated constructor stub  
  15.         TypedArray tArray = context.obtainStyledAttributes(attrs,R.styleable.PersonAttr);//获取配置属性  
  16.         String name = tArray.getString(R.styleable.PersonAttr_name);<span style="font-family: Arial, Helvetica, sans-serif;">//得到属性name</span>  
  17.         int age = tArray.getInt(R.styleable.PersonAttr_age, 15);  
  18.         Boolean adult = tArray.getBoolean(R.styleable.PersonAttr_adult, false);  
  19.         String str_adult = getAdultStatus(adult);  
  20.         int weight = tArray.getInt(R.styleable.PersonAttr_weight, 1);// 默认是中等身材,属性为:1  
  21.         String str_weight = getWeightStatus(weight);//获得肥胖属性  
  22.         float textSize = tArray.getDimension(R.styleable.PersonAttr_textSize,R.dimen.default_text_size);// 如果你设置为DP等单位,会做像素转换  
  23.         tArray.recycle();//回收资源  
  24. //      setTextSize(textSize);//设置字体大小  
  25.         setText("姓名:" + name + "\n" + "年龄:" + age + "\n" + "是否成年:" + str_adult  
  26.                 + "\n" + "体形:" + str_weight);//给自定义的控件赋值  
  27.     }  
  28.       
  29.     /** 根据传入的值判断是否成年 */  
  30.     public String getAdultStatus(Boolean adult ){  
  31.         String str_adult = "未成年";  
  32.         if (adult) {  
  33.             str_adult = "成年";  
  34.         }  
  35.         return str_adult;  
  36.     }  
  37.       
  38.     /** 根据传入的值判断肥胖状态 */  
  39.     public String getWeightStatus(int weight){  
  40.         String str_weight = "中等";  
  41.         switch (weight) {  
  42.         case 0:  
  43.             str_weight = "瘦";  
  44.             break;  
  45.         case 1:  
  46.             str_weight = "中等";  
  47.             break;  
  48.         case 2:  
  49.             str_weight = "肥胖";  
  50.             break;  
  51.         default:  
  52.             break;  
  53.         }  
  54.         return str_weight;  
  55.     }  
  56. }  

运行后就是:

这样,以后我们就可以根据这个方法,去自定义控件并自定义配置属性了,大大提高了自定义布局的使用效率。

对应的源码下载地址:下载地址

时间: 2024-12-06 11:07:20

android 自定义控件 使用declare-styleable进行配置属性(源码角度)的相关文章

Android中图片压缩方案详解及源码下载

Android中图片压缩方案详解及源码下载 图片的展示可以说在我们任何一个应用中都避免不了,可是大量的图片就会出现很多的问题,比如加载大图片或者多图时的OOM问题,可以移步到Android高效加载大图及多图避免程序OOM.还有一个问题就是图片的上传下载问题,往往我们都喜欢图片既清楚又占的内存小,也就是尽可能少的耗费我们的流量,这就是我今天所要讲述的问题:图片的压缩方案的详解. 1.质量压缩法 设置bitmap options属性,降低图片的质量,像素不会减少 第一个参数为需要压缩的bitmap图

android 手势密码 画图 有可以实现的源码

问题描述 android 手势密码 画图 有可以实现的源码 10C android 手势密码 还要用红色的线画出错误的图片,这个效果没有实现. 解决方案 Android招财进宝手势密码的实现Android招财进宝手势密码的实现Android招财进宝手势密码的实现 解决方案二: http://blog.csdn.net/wulianghuan/article/details/40536635 解决方案三: http://www.android100.org/html/201502/13/11838

Android编程实现网络图片查看器和网页源码查看器实例_Android

本文实例讲述了Android编程实现网络图片查看器和网页源码查看器.分享给大家供大家参考,具体如下: 网络图片查看器 清单文加入网络访问权限: <!-- 访问internet权限 --> <uses-permission android:name="android.permission.INTERNET"/> 界面如下:   示例: public class MainActivity extends Activity { private EditText ima

《Spark大数据分析实战》——2.4节配置Spark源码阅读环境

2.4 配置Spark源码阅读环境 由于Spark使用SBT作为项目管理构建工具,SBT的配置文件中配置了依赖的jar包网络路径,在编译或者生成指定类型项目时需要从网络下载jar包.需要用户预先安装git.在Linux操作系统或者Windows操作系统上(用户可以下载Git Shell,在Git Shell中进行命令行操作)通过"sbt/sbt gen-idea"命令,生成Intellij项目文件,然后在Intellij IDE中直接通过"Open Project"

Android编程实现网络图片查看器和网页源码查看器实例

本文实例讲述了Android编程实现网络图片查看器和网页源码查看器.分享给大家供大家参考,具体如下: 网络图片查看器 清单文加入网络访问权限: <!-- 访问internet权限 --> <uses-permission android:name="android.permission.INTERNET"/> 界面如下: 示例: public class MainActivity extends Activity { private EditText image

Android AsyncTask完全解析,带你从源码的角度彻底理解

我们都知道,Android UI是线程不安全的,如果想要在子线程里进行UI操作,就需要借助Android的异步消息处理机制.之前我也写过了一篇文章从源码层面分析了Android的异步消息处理机制,感兴趣的朋友可以参考 Android Handler.Message完全解析,带你从源码的角度彻底理解 . 不过为了更加方便我们在子线程中更新UI元素,Android从1.5版本就引入了一个AsyncTask类,使用它就可以非常灵活方便地从子线程切换到UI线程,我们本篇文章的主角也就正是它了. Asyn

Android RecyclerView的Item自定义动画及DefaultItemAnimator源码分析_Android

这是关于RecyclerView的第二篇,说的是如何自定义Item动画,但是请注意,本文不包含动画的具体实现方法,只是告诉大家如何去自定义动画,如何去参考源代码.  我们知道,RecyclerView默认会使用DefaultItemAnimator,所以如果我们需要自定义动画,那么应该好好的读读这个类的源代码,这样不仅仅是学习怎么自定义,还要学习Android的设计模式.  先弄明白一件事,DefaultItemAnimator继承自SimpleItemAnimator,SimpleItemAn

【android-tips】如何在android应用中插入百度广告(附源码)

(转载请注明出处:http://blog.csdn.net/buptgshengod) 1.介绍    现在游戏中的广告基本上已经成为了游戏创作者的一个重要的收入来源.其实插入广告还是挺简单的,本文选择百度广告联盟作为案例(总觉得百度不会拖欠工资).注:不过,插入广告程序会稍微卡一些,而且真的很耗流量. (本文并不是照抄百度的文档,会很直白哦) 2.代码部分    首先肯定是注册百度广告联盟的账号,和下载sdk.地址:http://munion.baidu.com/     第二步,打开ecli

Android RecyclerView的Item自定义动画及DefaultItemAnimator源码分析

这是关于RecyclerView的第二篇,说的是如何自定义Item动画,但是请注意,本文不包含动画的具体实现方法,只是告诉大家如何去自定义动画,如何去参考源代码. 我们知道,RecyclerView默认会使用DefaultItemAnimator,所以如果我们需要自定义动画,那么应该好好的读读这个类的源代码,这样不仅仅是学习怎么自定义,还要学习Android的设计模式. 先弄明白一件事,DefaultItemAnimator继承自SimpleItemAnimator,SimpleItemAnim