Android 自定义属性的理解和使用
2016-07-08 10:41
441 查看
一、引言
有时候Android传统的页面布局不足以满足我们的需求,常常需要自己定义view,通常继承View,然后重写构造方法以及onDraw等函数,再具体实现自己定义的复杂view。我们知道在给控件赋属性时,通常使用的是android系统自带的属性,比如
android:layout_height="wrap_content",除此之外,我们亦可以自己定义属性,这样在使用的时候我们就可以使用形如 testapp:testSize="15sp"的方式了
二、使用步骤
1.在项目文件res/value下面创建一个attrs.xml文件即自定义属性的声明文件,该文件中包含若干个attr集合,例如:<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="test"> <attr name="textSize" format="dimension"/> <attr name="texsColor" format="color"/> <attr name="type" format="integer"/> <attr name="background" format="reference"/> </declare-styleable> </resources>
其中resource是根标签,可以在里面定义若干个declare-styleable,<declare-styleable name="MyView">中name定义了属性集合的名称,下面可以再自定义多个属性,针对<attr name="testSize" format="dimension"/>来说,其属性的名称为"testSize",format指定了该属性类型为dimension,表示尺寸值。
format还可以指定其他的类型比如;
reference 表示引用,参考某一资源ID
string 表示字符串
color 表示颜色值
dimension 表示尺寸值
boolean 表示布尔值
integer 表示整型值
float 表示浮点值
fraction 表示百分数
enum 表示枚举值
flag 表示位运算
2.在使用到该自定义view的布局文件中键入一行代码,为该自定义属性添加命名空间,名称可以自己定义,在这我定义为testapp,并不要求一定是自定义view的名字,同时使用Eclipse和AS的在此有点区别:
Ecplise:其中com.cx.test为应用程序包名:
xmlns:testapp="http://schemas.android.com/apk/res/com.cx.test"
AS:以前写应用程序包名的方法被AS废弃掉了,直接使用res-auto:
xmlns:testapp="http://schemas.android.com/apk/res-auto"
接下来就可以在布局文件中使用自定义属性啦:
<com.cx.test.MyView android:layout_width="100dp" android:layout_height="100dp" testapp:textColor="#000000" testapp:textSize="15sp" testapp:type="1" />
3.在自定义view的代码中引入自定义属性,修改构造函数:
AttributeSet与TypedArray:
构造方法中的有个参数叫做AttributeSet(eg: MyView(Context context, AttributeSet attrs) )这个参数看名字就知道包含的是参数的集合,那么我能不能通过它去获取我的自定义属性呢?首先AttributeSet中的确保存的是该View声明的所有的属性,并且外面的确可以通过它去获取(自定义的)属性,怎么做呢?
其实看下AttributeSet的方法就明白了,下面看代码:
public class MyView extends View { private static String TAG=MyView.class.getSimpleName(); public MyView(Context context, AttributeSet attrs) { super(context, attrs); //使用AttributeSet获取属性 for (int i=0;i<attrs.getAttributeCount();i++){ Log.e(TAG, "MyView: =name=" + attrs.getAttributeName(i) + "=value=" + attrs.getAttributeValue(i)); } } }
输出:
E/MyView: MyView: =name=layout_width=value=100.0dip E/MyView: MyView: =name=layout_height=value=100.0dip E/MyView: MyView: =name=textSize=value=15.0sp E/MyView: MyView: =name=textColor=value=#ff000000 E/MyView: MyView: =name=type=value=1结果果然可以输出自定义view的所有属性,也就是通过AttributeSet可以获得布局文件中定义的所有属性的key和value(还有一些方法,自己去尝试)。
现在关注下一个问题:TypedArray是什么鬼?
我们简单修改下,布局文件中的View的属性:
<com.cx.test.MyView android:layout_width="100dp" android:layout_height="100dp" testapp:textColor="#000000" testapp:textSize="@dimen/mysize" testapp:type="1" testapp:bg="@drawable/aa" />此时输出:
E/MyView: MyView: =name=layout_width=value=100.0dip E/MyView: MyView: =name=layout_height=value=100.0dip E/MyView: MyView: =name=textSize=value=@2131230794 E/MyView: MyView: =name=textColor=value=#ff000000 E/MyView: MyView: =name=type=value=1 E/MyView: MyView: =name=bg=value=@2130837504
通过
AttributeSet获取的值,如果是引用都变成了@+数字的字符串。你说,这玩意你能看懂么?那么你看看最后一行使用TypedArray获取的值,是不是瞬间明白了什么。
TypedArray其实是用来简化我们的工作的,比如上例,如果布局中的属性的值是引用类型(比如:@dimen/myszie),如果使用
AttributeSet去获得最终的像素值,那么需要第一步拿到id,第二步再去解析id。而TypedArray正是帮我们简化了这个过程。
下面使用TypedArray:
public class MyView extends View { private static String TAG=MyView.class.getSimpleName(); public MyView(Context context, AttributeSet attrs) { super(context, attrs); //使用AttributeSet获取属性 // for (int i=0;i<attrs.getAttributeCount();i++){ // Log.e(TAG, "MyView: =name=" + attrs.getAttributeName(i) + "=value=" + attrs.getAttributeValue(i)); // } //使用TypedArray获取属性 TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.test); String textSize=ta.getString(R.styleable.test_textSize); int type=ta.getInteger(R.styleable.test_type,0); int color=ta.getColor(R.styleable.test_textColor, 0); Drawable drawable = ta.getDrawable(R.styleable.test_bg); Log.e(TAG, "MyView: =textSize=" + textSize + "=type=" + type+"=color="+color+"=drawable="+drawable); ta.recycle(); } }输出结果:
E/MyView: MyView: =textSize=20.0sp=type=1=color=-16777216=drawable=android.graphics.drawable.BitmapDrawable@428d6258可以看出使用TypedArray也可以获取布局文件中使用引用的属性。
通过比较可以看出我们在View的构造方法中,可以通过
AttributeSet去获得自定义属性的值,但是比较麻烦,而
TypedArray可以很方便的便于我们去获取。
相关文章推荐
- Android测试详解_1-Best Practices for Testing-介绍
- 自定义view实现涂鸦(画板)功能(二)
- Android ListView下拉刷新上拉自动加载更多DEMO示例
- Android如何调用第三方SO库
- 自定义ViewSwitcher, 支持自定义布局和轮播(淘宝头条效果)
- 解决AndroidStudio Can’t start Git:git.exe
- Android多媒体MediaStore运用
- Android开发ListView中下拉刷新上拉加载及带列的横向滚动实现方法
- Android仿zaker用手向上推动的特效开发【推动门效果】(附demo源码下载)
- Android中实现全屏、无标题栏的两种办法(另附Android系统自带样式的解释)
- 关于Fragment使用的一些见解
- android 的webview调用php服务器js , js 调用Android的webview
- (OK) init_install_android-x86_64_in_QEMU-KVM.sh
- Android 四大图片缓存原理、特性对比
- Android 系统编译
- Android(java)开发之将double类型,强制保留到小数点后两位解决方法。
- Android模块化编程——炫酷小巧多功能Button2
- 带Header与Footer的RecyclerViews
- Android fragment 重叠问题的解决方法
- Android Studio利用异步任务AsyncTask发送post请求获取json数据