Android自定义控件系列三:自定义开关按钮(三)--- 自定义属性

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

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

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

那么还是针对我们之前写的自定义控件:开关按钮为例来说,在之前的基础上,我们来看看有哪些属性是可以自定义的:按钮的背景图片,按钮的滑块图片,和按钮的状态(是开还是关),实际上都应该是可以在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 标签,分别代表我们需要定义的三个属性:按钮的背景图片,按钮的滑块图片,和按钮的状态;那么剩下的一个问题就是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的内容,感谢关注!

时间: 2024-12-06 18:22:06

Android自定义控件系列三:自定义开关按钮(三)--- 自定义属性的相关文章

[转]Android自定义控件系列五:自定义绚丽水波纹效果

出处:http://www.2cto.com/kf/201411/353169.html 今天我们来利用Android自定义控件实现一个比较有趣的效果:滑动水波纹.先来看看最终效果图: 图一 效果还是很炫的:饭要一口口吃,路要一步步走,这里我们将整个过程分成几步来实现 一.实现单击出现水波纹单圈效果: 图二 照例来说,还是一个自定义控件,这里我们直接让这个控件撑满整个屏幕(对自定义控件不熟悉的可以参看我之前的一篇文章:Android自定义控件系列二:自定义开关按钮(一)).观察这个效果,发现应该

Android自定义控件系列五:自定义绚丽水波纹效果

尊重原创!转载请注明出处:http://blog.csdn.net/cyp331203/article/details/41114551 今天我们来利用Android自定义控件实现一个比较有趣的效果:滑动水波纹.先来看看最终效果图: 图一 效果还是很炫的:饭要一口口吃,路要一步步走,这里我们将整个过程分成几步来实现 一.实现单击出现水波纹单圈效果: 图二 照例来说,还是一个自定义控件,这里我们直接让这个控件撑满整个屏幕(对自定义控件不熟悉的可以参看我之前的一篇文章:Android自定义控件系列二

Android自定义控件系列二:如何自定义属性

上一篇Android自定义控件系列一:如何测量控件尺寸 我们讲了如何确定控件的属性,这篇接着也是讲个必要的知识-如何自定义属性.对于一个完整的或者说真正有实用价值的控件,自定义属性是必不可少的. 如何为控件定义属性 在res/values/attrs.xml(attrs.xml如果不存在,可以创建个)中使用<declare-styleable>标签定义属性,比如我想定义个显示头像的圆形的图片控件(AvatarImageView): 01.<?xml version="1.0&q

Android自定义控件系列八:详解onMeasure()(二)--利用onMeasure测量来实现图片拉伸永不变形,解决屏幕适配问题

上一篇文章详细讲解了一下onMeasure/measure方法在Android自定义控件时的原理和作用,参看博文:Android自定义控件系列七:详解onMeasure()方法中如何测量一个控件尺寸(一),今天就来真正实践一下,让这两个方法大显神威来帮我们搞定图片的屏幕适配问题. 请尊重原创劳动成果,转载请注明出处:http://blog.csdn.net/cyp331203/article/details/45038329,非允许请勿用于商业或盈利用途,违者必究. 使用ImageView会遇到

Android自定义控件系列七:详解onMeasure()方法中如何测量一个控件尺寸(一)

转载请注明出处:http://blog.csdn.net/cyp331203/article/details/45027641 自定义view/viewgroup要重写的几个方法:onMeasure(),onLayout(),onDraw().(不熟悉的话可以查看专栏的前几篇文章:Android自定义控件系列二:自定义开关按钮(一)). 今天的任务就是详细研究一下protected void onMeasure(int widthMeasureSpec, int heightMeasureSpe

Android自定义控件系列之应用篇——圆形进度条

一.概述 在上一篇博文中,我们给大家介绍了Android自定义控件系列的基础篇.链接:http://www.cnblogs.com/jerehedu/p/4360066.html 这一篇博文中,我们将在基础篇的基础上,再通过重写ondraw()方法和自定义属性实现圆形进度条,效果如图所示: 二.实现步骤   1.  编写自定义组件MyCircleProgress扩展View public class MyCircleProgress extends View { - } 2.  在MyCircl

【android自定义控件】ProgressBar自定义

ProgressBar分为垂直和水平 经常在数据加载过程中,为了让用户感觉友好,弹出一个提示圆形的加载框 水平的经常在下载应用的时候用到,还伴随着下载进度. ProgressBar的样式有四种: android:progressBarStyle:默认进度条样式,不确定模式 android:progressBarStyleHorizontal:水平进度条样式 android:progressBarStyleLarge :大号进度条样式,也是不确定进度模式 android:progressBarSt

Android自定义控件系列 十:利用添加自定义布局来搞定触摸事件的分发,解决组合界面中特定控件响应特定方向的事件

这个例子是比较有用的,基本上可以说,写完这一次,以后很多情况下,直接拿过来addView一下,然后再addInterceptorView一下,就可以轻轻松松的达到组合界面中特定控件来响应特定方向的触摸事件了. 请尊重原创劳动成果,转载请注明出处:http://blog.csdn.net/cyp331203/article/details/45198549,非允许请勿用于商业或盈利用途,违者必究. 在写Android应用的过程之中,经常会遇到这样的情况:界面包含了多个控件,我们希望触摸在界面上的不

android自定义控件系列教程----视图的测量和布局

前面说点什么 当我们的一个视图界面绘制在android屏幕上面的时候其实都必须经过这几步measure. layout.draw这几个阶段,我们可以在view类里面看到这几个函数,然后里面有几个函数是onmeasure.onlayout.ondraw这几个函数是我们重写控件需要注意的这几个函数,下面我们就来讲讲这几个函数的功能和作用. onMeasure 正如这个函数的名子一样就是测量,所有的图示其实系统在绘制之前都不知道它到底有多大的,所以在很多时候我们在初始化界面oncreate的时候直接去