1,相信我们写过自定义控件的同学都会有一个疑问,自定义属性到底是怎么工作的,为什么要使用自定义属性呢,接下来结带着大家一起来学习学习,在学习这一篇的时候,可以下看看我的上一篇《从源码的角度一步步打造自己的TextView》,会对这篇有更好的理解

2,为什么要使用自定义属性

  我们要使用自定义属性的话首先要我们有这个自定义属性,那么我们常见的控件Textview的Android:text属性是怎么来的呢,我们来一起看一下系统的自定义属性源码,系统定义的所有属性我们可以在\sdk\platforms\Android-xx\data\res\values目录下找到attrs.xml这个文件,这里只找几个很常见的view属性

<declare-styleable name="View">
<attr name="id" format="reference" />
<attr name="background" format="reference|color" />
<attr name="padding" format="dimension" />
...
<attr name="focusable" format="boolean" />
...
</declare-styleable> <declare-styleable name="TextView">
<attr name="text" format="string" localization="suggested" />
<attr name="hint" format="string" />
<attr name="textColor" />
<attr name="textColorHighlight" />
<attr name="textColorHint" />
...
</declare-styleable> <declare-styleable name="ViewGroup_Layout">
<attr name="layout_width" format="dimension">
<enum name="fill_parent" value="-1" />
<enum name="match_parent" value="-1" />
<enum name="wrap_content" value="-2" />
</attr>
<attr name="layout_height" format="dimension">
<enum name="fill_parent" value="-1" />
<enum name="match_parent" value="-1" />
<enum name="wrap_content" value="-2" />
</attr>
</declare-styleable> <declare-styleable name="LinearLayout_Layout">
<attr name="layout_width" />
<attr name="layout_height" />
<attr name="layout_weight" format="float" />
<attr name="layout_gravity" />
</declare-styleable> <declare-styleable name="RelativeLayout_Layout">
<attr name="layout_centerInParent" format="boolean" />
<attr name="layout_centerHorizontal" format="boolean" />
<attr name="layout_centerVertical" format="boolean" />
...
</declare-styleable>

  首先我们知道我们所有的控件都是继承自view这个类的,所以view类所拥有的属性我们继承它的子类是全部都拥有的,而我们父view类却不能使用子view的特有的属性,充分的体现了我们的语言的多态性。再看看我们上面的标签,都有一个共同点,就是<declare-styleable name = "xxxx"> ,然后里面还有一堆的子标签,而这些子标签就表示这是这个XXX类的属性。但是并不是每个控件都能使用所有属性,LinearLayout中能使用layout_weight属性,而RelativeLayout却不能使用,因为layout_weight是为LinearLayout的LayoutParams定义的。

3,怎么自定义属性

  我们根据上面的源码我们知道,这两种的区别就是attr标签后面带不带format属性,如果带format的就是在定义属性,如果不带format的就是在使用已有的属性,name的值就是属性的名字,format是限定当前定义的属性能接受什么值。而系统定义的属性一般引用都用android:XXX引用,如果我们现在要定义一个text属性,所以我们可以有两种定义我们的方式

  常规方式:

<resources>
<declare-styleable name="MyTextView">
<attr name=“text" format="string" />
</declare-styleable>
</resources>

  引用系统已经定义好的:

<resources>
<declare-styleable name="MyTextView">
<attr name=“android:text"/>
</declare-styleable>
</resources>

  为什么这里我们还要引自系统属性呢,因为我们的MyTextView是继承的View,而android:text是TextView的特殊属性,所以这里必须要引用一下。

3,属性值的类型format

  format一共支持11种类型

  ① reference

  • 属性定义:
<declare-styleable name = "名称">
<attr name = "background" format = "reference" />
</declare-styleable>
  • 属性使用:
<ImageView android:background = "@drawable/图片ID"/>

  ② color

  • 属性定义:
<attr name = "textColor" format = "color" />
  • 属性使用:
<TextView android:textColor = "#00FF00" />

  ③boolean

  • 属性定义:
<attr name = "focusable" format = "boolean" />
  • 属性使用:
<Button android:focusable = "true"/>

  ④dimension

  • 属性定义:
<attr name = "layout_width" format = "dimension" />
  • 属性使用:
<Button android:layout_width = "42dip"/>

  ⑤float

  • 属性定义:
<attr name = "fromAlpha" format = "float" />
  • 属性使用:
<alpha android:fromAlpha = "1.0"/

  ⑥integer

  • 属性定义:
<attr name = "framesCount" format="integer" />
  • 属性使用:
<animated-rotate android:framesCount = "12"/>

  ⑦string

  • 属性定义:
<attr name = "text" format = "string" />
  • 属性使用:
<TextView android:text = "我是文本"/>

  ⑧fraction

  • 属性定义:
<attr name = "pivotX" format = "fraction" />
  • 属性使用:
<rotate android:pivotX = "200%"/>

  ⑨ enum:枚举值

  • 属性定义:
<declare-styleable name="名称">
<attr name="orientation">
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
</attr>
</declare-styleable>
  • 属性使用:
<LinearLayout
android:orientation = "vertical">
</LinearLayout>

  注意:当使用枚举属性的话不能在一个属性中同时使用两个值

  ⑩ flag:位或运算

  • 属性定义:
<declare-styleable name="名称">
<attr name="gravity">
<flag name="top" value="0x30" />
<flag name="bottom" value="0x50" />
<flag name="left" value="0x03" />
<flag name="right" value="0x05" />
<flag name="center_vertical" value="0x10" />
...
</attr>
</declare-styleable>
  • 属性使用:
<TextView android:gravity="bottom|left"/>

  位运算符在使用的时候可以使用多个属性

  ⑪混合类型:属性定义时可以指定多种类型值

  • 属性定义:
<declare-styleable name = "名称">
<attr name = "background" format = "reference|color" />
</declare-styleable>
  • 属性使用:
<ImageView
android:background = "@drawable/图片ID" />
或者:
<ImageView
android:background = "#00FF00" />

  以上就是所有的自定义属性的格式了,知道了这些,以后方便我们更准确的去定义自己的属性

4,在类中获取对应的自定义属性

  首先在attrs文件中添加我们的自定义属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyTextView2">
<attr name="myText" format="string"/>
<attr name="myTextColor" format="color"/>
<attr name="myTextSize" format="dimension"/>
</declare-styleable>
</resources>

  然后我们在布局文件中添加我们的自定义属性,这里要注意一下要引入我们的自定义空间,一般来说有两种:xmlns:mytextview="http://schemas.android.com/apk/res-auto”,res-auto表示自动查找,还有一种写法xmlns:mytextview="http://schemas.android.com/apk/com.example.myview",com.example.myview 为我们的应用程序包名。

<?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"
xmlns:myview="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<com.qianmo.activitydetail.MyTextView2
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00ff00"
myview:myText=" I Love You ......I Love You ......"
myview:myTextColor="#ff3399"
myview:myTextSize="25sp"
/> </LinearLayout>

  在构造方法中获取我们的自定义属性

 public MyTextView2(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
} /**
* 初始化数据
*/
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
//获取自定义属性的值
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyTextView2, defStyleAttr, 0);
mText = a.getString(R.styleable.MyTextView2_myText);
mTextColor = a.getColor(R.styleable.MyTextView2_myTextColor, Color.BLACK);
mTextSize = a.getDimension(R.styleable.MyTextView2_myTextSize, 30f);
a.recycle(); //初始化Paint数据
mPaint = new Paint();
mPaint.setColor(mTextColor);
mPaint.setTextSize(mTextSize); //获取绘制的宽高
mBound = new Rect();
mPaint.getTextBounds(mText, 0, mText.length(), mBound);
Log.i(TAG, "mText :" + mText + ",mTextColor:" + mTextColor+ ",mTextSize:" + mTextSize);
}

  打印结果如下:

mText : I Love You ......I Love You ......,mTextColor:-52327,mTextSize:65.625

  ok,这样我们的就本上使用上了自定义属性,但是在使用的时候我们发现了两个陌生的类AttributeSet和TypeArray类,下面让我们来了解了解吧

5,AttributeSet和TypeArray的了解

  Attributeset看名字就知道是一个属性的集合,实际上,它内部就是一个XML解析器,帮我们将布局文件中该控件的所有属性解析出来,并以key-value的兼职对形式维护起来。其实我们完全可以只用他通过下面的代码来获取我们的属性就行。

//打印AttributeSet中的值
for (int i = 0; i < attrs.getAttributeCount(); i++) {
Log.i(TAG, "name:" + attrs.getAttributeName(i) + ",value:" + attrs.getAttributeValue(i));
}

  看看我们打印出来的结果

03-21 03:24:44.339 12206-12206/com.qianmo.activitydetail I/MyTextView: getWidth():1080,getHeight(): 1731
03-21 03:30:59.950 17617-17617/com.qianmo.activitydetail I/MyTextView: name:background,value:#ff00ff00
03-21 03:30:59.950 17617-17617/com.qianmo.activitydetail I/MyTextView: name:layout_width,value:-1
03-21 03:30:59.950 17617-17617/com.qianmo.activitydetail I/MyTextView: name:layout_height,value:-1
03-21 03:30:59.950 17617-17617/com.qianmo.activitydetail I/MyTextView: name:myText,value: I Love You ......I Love You ......
03-21 03:30:59.950 17617-17617/com.qianmo.activitydetail I/MyTextView: name:myTextColor,value:#ffff3399
03-21 03:30:59.950 17617-17617/com.qianmo.activitydetail I/MyTextView: name:myTextSize,value:25.0sp

  可以看到使用Attributeset得到的属性的值是取到的xml文件中的值,而我们想要的textsize的大小,还得想方法将sp去掉才能拿到我们的25.0,这时候我们就需要一个人帮我们来这样做了,而typeArray就顺势而生了,我们来看看使用TypeArray得到的数据

 TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyTextView2, defStyleAttr, 0);
mText = a.getString(R.styleable.MyTextView2_myText);
mTextColor = a.getColor(R.styleable.MyTextView2_myTextColor, Color.BLACK);
mTextSize = a.getDimension(R.styleable.MyTextView2_myTextSize, 30f);
a.recycle();
Log.i(TAG, "mText :" + mText + ",mTextColor:" + mTextColor + ",mTextSize:" + mTextSize);

  打印的结果

mText : I Love You ......I Love You ......,mTextColor:-52327,mTextSize:65.625

  这样的数据就是我们想要的了,这样我们就了解的差不多了,See You Next Time !

Android -- 深入了解自定义属性的更多相关文章

  1. Android自定义控件之自定义属性

    前言: 上篇介绍了自定义控件的基本要求以及绘制的基本原理,本篇文章主要介绍如何给自定义控件自定义一些属性.本篇文章将继续以上篇文章自定义圆形百分比为例进行讲解.有关原理知识请参考Android自定义控 ...

  2. Android之创建自定义属性

    一. 在res/values 文件下定义一个attrs.xml 文件.代码如下: <?xml version="1.0" encoding="utf-8" ...

  3. Android中的自定义属性的实现

    Android开发中,如果系统提供的View组件不能满足我们的需求,我们就需要自定义自己的View,此时我们会想可不可以为自定义的View定义属性呢?答案是肯定的.我们可以定义自己的属性,然后像系统属 ...

  4. Android自定义控件及自定义属性

    Android自定义控件及自定义属性 自定义控件 创建自定义控件 自定义一个类,继承View 继承View还是哪个类,取决于你要实现一个什么样的控件 如果你要实现的是一个线性布局的组合控件,就可以继承 ...

  5. Android 手机卫士--自定义属性

    在前面的文章中,已经实现了“设置中心”第一栏的功能以及布局 本文地址:http://www.cnblogs.com/wuyudong/p/5936016.html,转载请注明出处. 自定义属性声明 接 ...

  6. Android自定义View自定义属性

    1.引言 对于自定义属性,大家肯定都不陌生,遵循以下几步,就可以实现: 自定义一个CustomView(extends View )类 编写values/attrs.xml,在其中编写styleabl ...

  7. android 自定义控件,自定义属性设置

    做listView的上拉下拉刷新,网上找了个历程.但是有些界面只有上拉刷新,有些界面是下拉刷新.觉得应该在xml里定义一个属性控制上下拉使能. 0.关于自定义控件: 自定义控件设计主要方式有:a) 继 ...

  8. Android 深入理解Android中的自定义属性

    转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/45022631: 本文出自:[张鸿洋的博客] 1.引言 对于自定义属性,大家肯定 ...

  9. [Android UI] ActionBar 自定义属性

    actionbar 默认放在顶部, 如果在application或者activity中加入 android:uiOptions="splitActionBarWhenNarrow" ...

随机推荐

  1. [leetcode-500-Keyboard Row]

    Given a List of words, return the words that can be typed using letters of alphabet on only one row' ...

  2. Ubantu 16.4 samba安装配置

    本文总结了Ubantu 16.04 环境下的samba安装.配置及使用.本文为原创,也是我的第一篇博客,以后会经常写博客,记录自己的学习.总结及研究,让博客见证着我成长的轨迹. 下文中的所有命令均使用 ...

  3. Linux配置LNMP环境(二)配置PHP

    前言:本教程安装的PHP版本php-5.6.30(官方最后更新日期2017-01-19),教程编写日期2017-07-02.本教程中的下载地址是在写教程的时候从官方复制的,时间过长可能会有变化. 安装 ...

  4. haproxy+tomcat集群搭建

    web1和web2的部署可参考我之前的文章<Tomcat集群搭建>,这里就省去该过程了. #安装haproxy- .tar.gz cd haproxy-/ make TARGET=linu ...

  5. 2238"回文字串"报告

    题目描述: 回文串,就是从前往后和从后往前看都是一样的字符串.那么现在给你一个字符串,请你找出该字符串中,长度最大的一个回文子串. 输入描述: 有且仅有一个仅包含小写字母的字符串,保证其长度不超过50 ...

  6. NEWS-包名-baseTest-类名-ConfigManager

    package baseTest; import java.io.IOException;import java.io.InputStream;import java.util.Properties; ...

  7. usaco training 4.1.1 麦香牛块 题解

    Beef McNuggets题解 Hubert Chen Farmer Brown's cows are up in arms, having heard that McDonalds is cons ...

  8. Ajax获取数据的几种格式和解析方式

    一.什么是ajax  AJAX的全称是Asynchronous JavaScript and XML(是异步的 javascript 和 XML).  ajax不是新的编程语言,而是一种使用现有标准的 ...

  9. 部署服务能在Dynamics CRM Online上使用吗?

    部署服务有些时候有用,改动一些参数不需要重启IIS,也不需要去数据库中更改.比如,系统默认设置一个仪表盘(Dashboard)最多6个组件,不能超过这个数量,通过部署服务是可以更改的.部署服务既可以通 ...

  10. 利用HTML5判断用户是否正在浏览页面技巧

    现在,HTML5里页面可见性接口就提供给了程序员一个方法,让他们使用visibilitychange页面事件来判断当前页面可见性的状态,并针对性的执行某些任务.同时还有新的document.hidde ...