Android自己定义控件系列四:自己定义开关button(三)--- 自己定义属性

尊重原创,转载请注明出处:http://blog.csdn.net/cyp331203/article/details/40855377


接之前的:Android自己定义控件系列二:自己定义开关button(一Android自己定义控件系列三:自己定义开关button(二)继续,今天要讲的就是怎样在自己定义控件中使用自己定义属性,实际上这里有两种方法。一种是配合XML属性资源文件的方式,还有一种是不须要XML资源文件的方式;以下我们分别来看看:


一、配合XML属性资源文件来使用自己定义属性:


那么还是针对我们之前写的自己定义控件:开关button为例来说,在之前的基础上,我们来看看有哪些属性是能够自己定义的:button的背景图片,button的滑块图片,和button的状态(是开还是关),实际上都应该是能够在xml文件里直接定义的。



最好还是先来看看之前我们在代码中不依靠自己定义属性的时候,是怎样写的。我们能够在initView方法中找到这样几行代码:

backgroundBitmap = BitmapFactory.decodeResource(getResources(),
		 R.drawable.switch_background);
		 
slideButton = BitmapFactory.decodeResource(getResources(),
		 R.drawable.slide_button);
		 
currentState=false;

会发现,我们是直接引用的资源文件,而不是在布局xml文件里使用的定义属性的方式。以下我们一步步来看看要怎么样做才干够定义使用上自己定义属性:


第一步:在res/values目录中加入attrs.xml文件


实际上,这个文件名称并不一定要写成attrs.xml,可是依照安卓源代码的写法而且也便于别人查看代码的时候明白这个文件的用意,还是写成attrs.xml。

以下要怎样写呢,我们还是能够參看一下安卓的源代码:打开源代码目录下\frameworks\base\core\res\res\values\attrs.xml文件,我们会发现这里面定义了非常多attr的标签,里面不乏一些我们常见的属性:

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

等等,在layout_width这个标签上面我们还能够发现一个

<declare-styleable name="ViewGroup_Layout">

declare-styleable标签的里包括了非常多根ViewGruop相关的属性。

而在这个attrs.xml文件的最外面,是一个<resources>的标签


到这里,我们基本上就明确了一个attrs.xml文件的结构了:

首先要一个<resources>的父标签。然后里面能够包括一个declare-styleable的标签,在这个标签里面我们再定义出三个attr 标签,分别代表我们须要定义的三个属性:button的背景图片。button的滑块图片,和button的状态;那么剩下的一个问题就是attr标签中的format代表什么意思。实际上format代表的是这条属性的值的类型:  

    1.reference:參考指定Theme中资源ID,这个类型意思就是你传的值能够是引用资源  
     2.string:字符串,假设你想别人既能直接写值也能够用类似"@string/test"引用资源的方式,能够写成format="string|reference"  
     3.Color:颜色  
     4.boolean:布尔值  
     5.dimension:尺寸值  
     6.float:浮点型  
     7.integer:整型  
     8.fraction:百分数  
     9.enum:枚举 ,假设你提供的属性仅仅能让别人选择,不能随便传入,就能够写成这样  
        <attr name="language">  
                <enum name="china" value="1"/>  
                <enum name="English" value="2"/>  
        </attr>  

     10.flag:位或运算


declare-styleable子元素:  
  
定义一个styleable对象,每一个styleable对象就是一组attr属性的集合 注意:这里的name属性并非一定要和自己定义类名同样,仅仅是为了好区分相应类的属性而已  
  
  
注意:上面的属性资源文件定义了该属性之后,至于究竟是哪个自己定义View组件中来使用该属性,该属性究竟能发挥什么作用, 就不归该属性资源文件管了,也就是说这个属性资源文件是个公共的,大家都能够用,可是为了方便管理。一般都是一个自己定义View里的属性写成一个declare-styleable集合.属性资源所定义的属性究竟能够返回什么作用,取决于自己定义组件的代码实现  


在这里。我们的attrs.xml文件写成以下这样:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="MyToggleButton">
        <attr name="current_state" format="boolean" />
        <attr name="backgroundBitmap" format="reference" />
        <attr name="slideButton" format="reference" />
    </declare-styleable>

</resources>



第二步:在自己定义控件的类中拿到attrs.xml文件里定义的属性的相应的值,然后赋值给我们须要设置的变量,在这里就是 背景图片,滑块图片和开关状态 这三个值。


要怎样做呢?我们先将上面给出的

backgroundBitmap = BitmapFactory.decodeResource(getResources(),
		 R.drawable.switch_background);
		 
slideButton = BitmapFactory.decodeResource(getResources(),
		 R.drawable.slide_button);
		 
currentState=false;

这三句凝视掉。然后换成以下的代码:

 /*这里取得declare-styleable集合*/ 
		TypedArray typedArray = context.obtainStyledAttributes(attrs,
				R.styleable.MyToggleButton);
		
		/*取得本集合里面总共同拥有多少个属性*/
		int indexCount = typedArray.getIndexCount();
		
		/*遍历这些属性,拿到属性相应的id,然后通过id拿到相应的值*/
		for (int i = 0; i < indexCount; i++) {
			
			/*拿到相应的id值taId*/
			int taId = typedArray.getIndex(i);
			switch (taId) {
			case R.styleable.MyToggleButton_backgroundBitmap:
				// drawable转bitmap
				backgroundBitmap = ((BitmapDrawable) typedArray
						.getDrawable(taId)).getBitmap();
				break;
			case R.styleable.MyToggleButton_current_state:
				currentState = typedArray.getBoolean(taId, false);

				break;

			case R.styleable.MyToggleButton_slideButton:
				slideButton = ((BitmapDrawable) typedArray.getDrawable(taId))
						.getBitmap();
			default:
				break;
			}

		}

凝视也比較详尽了。基本思路就是先拿到相应MyToggleButton这个名字的declare-styleable集合相应的TypedArray对象,然后依据TypedArray对象来遍历获取相应的资源并赋值。


第三步:在布局文件里使用自己定义属性,并设置属性值:

<com.example.myattrsdemo.ui.MyView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        alex:test_bitmap="@drawable/pigs"
        alex:test_id="1"
        alex:test_msg="我的自己定义属性实例" />

在上面的代码,我们发现我们写成了alex:这种标头。这个实际上是命名空间的简写,所以我们必需要加入一个命名空间,參看一下Android的命名空间是怎样写的:

xmlns:android="http://schemas.android.com/apk/res/android"


在这里xmlns:android里面的android,是能够变化的。这里我们就改为alex,然后对于http://schemas.android.com/apk/res/android这个部分,最后的android也要改的,这里必须改成整个应用的包名,我们能够去清单文件里查找,这里是com.example.togglebutton,所以整个写下来就是:xmlns:alex="http://schemas.android.com/apk/res/com.example.togglebutton"

于是这里一个完整的布局文件写为:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:alex="http://schemas.android.com/apk/res/com.example.togglebutton"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >

    <com.example.togglebutton.ui.MyToggleButton
        android:id="@+id/my_toggle_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        alex:backgroundBitmap="@drawable/switch_background"
        alex:current_state="true"
        alex:slideButton="@drawable/slide_button" />

</RelativeLayout>

至此,一个完整的自己定义属性的流程就完毕了。我们能够直接在布局文件里改动我们自己定义的那三个属性。就能够在执行的时候看到不同的效果,这样显得比較高大上了。


二、不须要XML资源文件的方式来使用自己定义属性:


既然没有attrs.xml,那么也不须要命名空间了。我们直接在上面的布局文件里加上一句:

test_text="測试不须要XML资源文件的方式来使用自己定义属性"

然后我们就能够在java中将其获取出来,这里我们仅仅做简单的打印工作:

		// 无命名空间測试

		String attributeValue = attrs.getAttributeValue(null, "test_text");
		System.out.println(attributeValue);

执行结果:


依照这个思路,上面我们定义的三个属性都能够改为不须要命名空间的方式,看起来是非常方便的。可是实际上有弊端:

命名空间能够不要,属性名就要自己相应好了,不然程序取不到,不像有XML资源文件配合的方式有个约束。 


至此。自己定义控件三部曲就完毕了。随后会增加自己定义ViewGroup的内容,感谢关注。










posted on 2017-05-03 14:11  ljbguanli  阅读(165)  评论(0编辑  收藏  举报