最近在学习的过程中遇到了自定义的attr和自定义的style。因此各种百度,各种博客的学习,算是有了一个系统的了解。在这里记录下自己的收获。
一、为什么要使用自定义attr以及本文定位
在android开发中,很多时候需要我们自定义view,这其中就包含了一个view的很多属性的设置。有时候会出现android本身提供的属性并不够用(比如它针对某些控件提供的text属性,color属性等),又或者我们想将android系统提供的属性集成到一起形成自己的一套属性集合。那么这个时候,就需要我们来自定义一套自己的属性,这就是自定义attr。因此自定义attr与自定义view是密切关联的。对于自定义attr更加深入的理解,在这里推荐我十分佩服的一位大神的博客文章http://blog.csdn.net/lmj623565791/article/details/45022631
但是建议你还是阅读完本文,再去点击上面的链接。因为本文将手把手带你去实现一个自定义的attr,这样子你会了解整个自定义attr流程。既然是手把手,所以本文不会涉及到原理性的东西,而且代码十分简单易懂,因为我也是初学者,所以力求将一个初学者学习的过程展现出来,当然其中的某些疑问可能对于anroid老鸟来说是十分幼稚的。不过知识就是这样子一点点一步步收获起来的。好了,废话不多说,进入正文吧。
二、你必须要了解的
首先实现一个自定义attr的流程:
(1)先有一个自定义的view(它是你所自定义attr的使用者)
(2)然后在values文件夹下建立attrs.xml文件,编写你的自定义的属性。示例代码如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 4 <declare-styleable name="test"> 5 <attr name="text" format="string" /> 6 <attr name="testAttr" format="integer" /> 7 </declare-styleable> 8 9 </resources>
(3)在xml文件中使用自定义属性,为它赋值
(4)在自定义view中使用TypedArray获取你所赋的值,并用作其他用途。
现在主要说明编写自定义属性的代码中,即上面的xml文件中,format的含义。其实format就是为自定义的属性设置一个格式。这根android给我们提供的属性是一样的道理,比如android给我们提供的text的属性格式就是string类型的,在我们为一个TextView设置text的时候可不就是写一个字符串嘛。那么上面的代码的意思就是自定义的属性text,格式是string类型,testAttr,类型是integer。下面来看一个format都可以指定为什么。如下:
format还可以指定其他的类型比如; reference 表示引用,参考某一资源ID string 表示字符串 color 表示颜色值 dimension 表示尺寸值 boolean 表示布尔值 integer 表示整型值 float 表示浮点值 fraction 表示百分数 enum 表示枚举值 flag 表示位运算
可能还还有其他的疑问,比如其他关键字的含义是什么,以及是怎么使用自定义attr的。甚至还有很细的说不清的疑问。如果没有实际代码的话,很难说明白这些疑问。所以跟着我来往下一步一步写一个例子出来吧,在这个过程中,相信你的疑问应该会被解开。
三、实现自定义attr,同时解答细节上的疑问
在这个例子中,我们来实现超级简单的自定义view,在屏幕上写用画笔写出一个字符串出来。纯粹是为了说明自定义attr的实现过程的。而字符串的颜色以及字符串的内容,就采用自定义属性的方式来获取。我们心中已经有了这个自定义的view的大概了,下面就开始编写自定义attr吧。
新建项目,然后在它的res/values下面新建attrs.xml文件,代码如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 <declare-styleable name="MyView"> 4 <attr name="myText" format="string"/> 5 <attr name="myColor" format="color"/> 6 </declare-styleable> 7 </resources>
从代码中我们可以看到,自定义了两个属性,myText和myColor,类型分别为string何color。然后要说明两点:
(1)你可以将declare-styleable看成一个集合的名称,而它里面的元素就是我们自定义的属性。它可以命名为任意名称,不过一般都命名为相应的自定义的view的名称,表示是为这个view定制的属性,也方便查阅。在这里我随便命名了一个名字,为MyView。通过这个名称就可以找到我们自定义的属性。resources标签下可以有多个declare-styleable的。
(2)标签attr下的name就是自定义的属性名,可以任意命名,format为其格式类型。
你肯定还在疑问,自定义的属性都自定义好了,怎么用呢?那么我们现在就来使用它。首先将与之相关的自定义的view先建出来。新建类CustomView继承自view,代码如下:
1 package com.fuly.kun; 2 3 import android.content.Context; 4 5 import android.view.View; 6 7 public class CustomView extends View { 8 9 public CustomView(Context context, AttributeSet attrs) { 10 super(context, attrs); 11 12 } 13 14 }
代码很简单,在这个自定义的view中,我们什么都没有做。这个view肯定是要显示出来的,那么我就修改activity_main.xml的代码,将其显示出来。注意这个时候,就该为CustomView设定属性了,此时就开始使用自定义的attr了。好了,快看代码吧,代码:
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 xmlns:fuly="http://schemas.android.com/apk/res/com.fuly.kun" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 > 7 8 <com.fuly.kun.CustomView 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 fuly:myText="我是自定义attr" 12 fuly:myColor="#00ff00"/> 13 </RelativeLayout>
代码很简单,我们给自定义的view赋了属性值。是不是发现了什么,有些代码跟你之前用的不一样!下面我们就来详细说明一下怎么就把自定义的属性给使用进来了。如下说明:
(1)首先观察代码的第3行,这句话就是引入了我们项目中自定义的attr。是不是发现第三行和第一行的代码很像,其实你现在明白了吧,第一行其实就是因为android系统给出的属性,所以下面我们才能使用android:layout_width等。因为引入自定义attr,主要将后缀的android替换成为项目的包名即可,即替换为了Manifest.xml下的package标签下的包名。而我们将引入的自定义attr命名为了fuly,然后在使用自定义属性时就借助fuly来找到我们自定义的属性名称了。fuly这个名称可以随便指定,没有什么规则。
(2)再观察第11行和第12行的代码,跟第9行和第10行的代码是不是很像,这就是在CustomView使用自定义的属性,并为其赋值(一定要注意和其格式类型要相同)。
好了,现在要修改CustomView的代码了。获取到我们自定义的属性值,并使用它。这其实跟android获取自带的属性是一样的道理,比如我们给一个TextView的text赋了一个字符串,然后在代码中使用getText()方法就可以这个字符串,即给text所赋的属性值。好了,快看代码吧,如下:
1 package com.fuly.kun; 2 3 import android.content.Context; 4 import android.content.res.TypedArray; 5 import android.graphics.Canvas; 6 import android.graphics.Paint; 7 import android.util.AttributeSet; 8 import android.view.View; 9 10 public class CustomView extends View { 11 12 private TypedArray ta;//用来获取自定义属性的 13 14 15 public CustomView(Context context, AttributeSet attrs) { 16 super(context, attrs); 17 //获取到我们自定义的属性 18 ta = context.obtainStyledAttributes(attrs, R.styleable.MyView); 19 } 20 21 protected void onDraw(Canvas canvas) { 22 23 super.onDraw(canvas); 24 //获取到我们为自定义的属性所赋的值 25 String text = ta.getString(R.styleable.MyView_myText); 26 int color = ta.getColor(R.styleable.MyView_myColor, 003300); 27 28 Paint paint = new Paint(); 29 paint.setColor(color); 30 paint.setTextSize(55); 31 canvas.drawText(text, 100, 100, paint); 32 } 33 34 }
代码很简单。只不过就牵涉了一个知识点,获取自定义属性的值,要使用TypedArray这个类而已。在代码的第18行,我们获取了一个TypedArray实例,而且这个实例是跟我们自定义的属性集合MyView相关联的。然后再代码的第25和26行,就可以用这个TypedArray对象获取自定义属性的值了。注意ta.getColor的第二个参数意思是如果该属性没有赋值,就返回颜色“#003300”。然后我们将获取到的文本和颜色作用到画笔和画布上即可。
好了,MainActivtity中的代码已经加载了acitivty_main.xml布局,不需要更改。下面我们直接运行效果,如下:
小结:
主要是TypedArray的对象的获得,是通过Context的,如下:
ta = context.obtainStyledAttributes(attrs, R.styleable.MyView);
关于它的一系列方法,可以翻看API文档,这里总结没有什么意义。
好了,相信对自定义attr有了一个初步的了解了吧。以后程序开发中要比这个里复杂的多。学习进阶,不要怕难,贵在坚持!一起进步