之前在自定义View理论中,遗留下了一个知识,就是具体的自定义属性到底怎么使用。本篇就对自定义属性的常见方式,做详细的整理。分析自定义属性的常见三种方式。
我们知道,大部分情况我们的自定义View需要有更多的灵活性,比如我们在xml中指定了颜色大小等属性,在程序运行时候控件就能展示出相应的颜色和大小。所以我们需要自定义属性。我们还知道,当在布局文件中加入某个控件的时候,会调用该View的构造方法 XXXView(Context context,AttributeSet attribute);当我们在 xml中创建了一个view时,xml会被解析,显示解析用pull解析xml文件,解析成键值对,对象的封装成AttributeSet 对象;根据元素名,有类的全名就可以反射实例化该类,得到AttributeSet 该类,就得到属性值。我们只需要在这个参数中就可以获取所有自定义的属性值了。
如何自定义属性?
在自定义属性前,先看看系统是怎么定义属性的。(查看View类的属性)
找到系统attrs目录:
D:\prograssinstall\as\SDK\platforms\android-23\data\res\values,点击打开。
看一下View类的属性情况:
<declare-styleable name="View">
<!-- Supply an identifier name for this view, to later retrieve it
with {@link android.view.View#findViewById View.findViewById()} or
{@link android.app.Activity#findViewById Activity.findViewById()}.
This must be a
resource reference; typically you set this using the
<code>@+</code> syntax to create a new ID resources.
For example: <code>android:id="@+id/my_id"</code> which
allows you to later retrieve the view
with <code>findViewById(R.id.my_id)</code>. -->
<attr name="id" format="reference" />
<!-- Supply a tag for this view containing a String, to be retrieved
later with {@link android.view.View#getTag View.getTag()} or
searched for with {@link android.view.View#findViewWithTag
View.findViewWithTag()}. It is generally preferable to use
IDs (through the android:id attribute) instead of tags because
they are faster and allow for compile-time type checking. -->
<attr name="tag" format="string" />
<!-- The initial horizontal scroll offset, in pixels.-->
<attr name="scrollX" format="dimension" />
<!-- The initial vertical scroll offset, in pixels. -->
<attr name="scrollY" format="dimension" />
<!-- A drawable to use as the background. This can be either a reference
to a full drawable resource (such as a PNG image, 9-patch,
XML state list description, etc), or a solid color such as "#ff000000"
(black). -->
<attr name="background" format="reference|color" />
<!-- Sets the padding, in pixels, of all four edges. Padding is defined as
space between the edges of the view and the view's content. A views size
will include it's padding. If a {@link android.R.attr#background}
is provided, the padding will initially be set to that (0 if the
drawable does not have padding). Explicitly setting a padding value
will override the corresponding padding found in the background. -->
<attr name="padding" format="dimension" />
.........................................
拿<attr name="background" format="reference|color" />举例,这里制定了属性名称,以及该属性的类型是引用类型和color类型。类型代表,我可以通过什么方式给属性赋值。比如我们通常设置背景可以这么写:background="@R.drawable/a.png";或者background="#ff0000".相信,看到这里肯定能够意会了吧。
细心的你,会发现每一个配置文件中有一行命名间:xmlns:Adroid="http://schemas.android.com/apk/res/android" 这是系统自带的,它的原理是:通过命名空间的前缀android,找到包的信息(这里是最后一个名称android),通过包的信息,找到工程,找到工程后。就可以找到这个工程的资源信息(values----attrs属性配置文件),从attrs文件里找到属性配置的信息。
了解了系统的定义属性原理,我们开始自定属性。标准的步骤如下:
1_创建工程:包名:com.itydl.a06attributetest
建议用UTF-8编码
2_创建属性类MyAttributeView继承View
3_创建工程的属性文件attrs.xml和常见属性类型
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:itydl="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.itydl.a06attributetest.MainActivity">
<com.itydl.a06attributetest.MyAttributeView
itydl:my_age ="25dp"
itydl:my_name="android_attribute"
itydl:my_bg="@drawable/test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>
其中itydl是自己的命名空间。
4_使用自定义类和自定义属性
在res/values/下新建attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 定义一个名字叫MyAttributeView属性集合,name往往跟对应的View的类名一致 -->
<declare-styleable name="MyAttributeView">
<!--定义一个类型为integer,名字叫my_age的属性 -->
<attr name="my_age" format="integer"/>
<!--定义一个类型为string,名字叫my_name的属性 -->
<attr name="my_name" format="string"/>
<!--定义一个类型为reference和color(这样背景可以通过R引用,
也可以使用图片资源),名字叫my_bg的属性 -->
<attr name="my_bg" format="reference|color"/>
</declare-styleable>
</resources>
5_三种方式得到属性值
// 1.用命名空间取对应的属性- String
String name = attrs.getAttributeValue(
"http://schemas.android.com/apk/res-auto",
"my_name");
String my_age = attrs.getAttributeValue(
"http://schemas.android.com/apk/res-auto",
"my_age");
String my_bg = attrs.getAttributeValue(
"http://schemas.android.com/apk/res-auto",
"my_bg");
// System.out.println(name+","+my_age+","+my_bg);
// 2.遍历方式取属性String 和int
for (int i = 0; i < attrs.getAttributeCount(); i++) {
System.out.println(attrs.getAttributeValue(i) + ":"
+ attrs.getAttributeName(i));
}
// 3.用系统工具TypedArray取属性- 取各种值Bitmap String 等等
//参数1:自定义属性集合类;参数2:自动生成的自定义属性类名称的资源id(它是一个数组)
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyAttributeView);
//a.getIndexCount()获取属性个数
for (int i = 0; i < a.getIndexCount(); i++) {
int index = a.getIndex(i);//所有属性对应的id
switch (index) {
case R.styleable.MyAttributeView_my_age://年龄属性id与之匹配
mAgeInt = a.getInt(i, 0);
break;
case R.styleable.MyAttributeView_my_name://姓名
mName = a.getString(i);
break;
case R.styleable.MyAttributeView_my_bg://背景图片id
//拿到图片,Drawable类型
Drawable drawable = a.getDrawable(i);
//我们需要的bitmap类型的图片
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
mBitmap = bitmapDrawable.getBitmap();
break;
default:
break;
}
}
6_把取到的属性值给给画出来
@Override
protected void onDraw(Canvas canvas) {
canvas.drawText(mName + "-------------" + mAgeInt,50,50,mPaint);
canvas.drawBitmap(mBitmap,50,50,mPaint);
}
format 常用类型
reference 引用
color 颜色
boolean 布尔值
dimension 尺寸值
float 浮点值
integer 整型值
string 字符串
enum 枚举
具体使用情况可以google~
有点帮助的话可以关注哈,有问题大家一起交流。也可以动手微信扫描下方二维码查看更多安卓文章:
打开微信搜索公众号 Android程序员开发指南 或者手机扫描下方二维码 在公众号阅读更多Android文章。
微信公众号图片: