Android 自定义属性
来源:互联网 发布:荼靡电视剧大结局知乎 编辑:程序博客网 时间:2024/05/18 06:20
思考:
我们使用Android组件的时候,大多数都是在xml中定义View,然后设置它的属性,那么的它的属性又是怎么被解析应用的呢?
我们又该怎样去自定义属性呢?
activity_main.xml 布局文件代码如下:
看到没attrs 其实就是咱在定义xml中定义的属性.通过观察还可以发现,是不是 id获取的为@XXX,没有得到正确的数值,这是因为id为引用类型,需要经过两次处理,或者用TypedArray来处理(后面还会重点提到).
那么com.android.internal.R.styleable.View 是什么鬼呢?其实知道自定义属性的几个步骤的,就知道其中有一步是在attrs.xml中申明 自定义属性:
比如说 name="mytv" 通过declare-styleable来申明的,会在R.java文件中,定义如下类属性:
看到了系统自定义属性,我们再回过头来看看 View的构造方法中这样一行代码:
我们使用Android组件的时候,大多数都是在xml中定义View,然后设置它的属性,那么的它的属性又是怎么被解析应用的呢?
我们又该怎样去自定义属性呢?
View属性解析过程认识
我们首先要知道,在解析XML的属性并赋值的过程都是在该View的构造方法中体现的,比如就拿我们的View类来说,它的构造方法部分代码如下:public View(Context context, AttributeSet attrs, int defStyleAttr) { this(context); TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View, defStyleAttr, 0); Drawable background = null; final int N = a.getIndexCount(); for (int i = 0; i < N; i++) { int attr = a.getIndex(i); switch (attr) { case com.android.internal.R.styleable.View_background: background = a.getDrawable(attr); break; case com.android.internal.R.styleable.View_padding: padding = a.getDimensionPixelSize(attr, -1); mUserPaddingLeftInitial = padding; mUserPaddingRightInitial = padding; leftPaddingDefined = true; rightPaddingDefined = true; break; case com.android.internal.R.styleable.View_paddingLeft: leftPadding = a.getDimensionPixelSize(attr, -1); mUserPaddingLeftInitial = leftPadding; leftPaddingDefined = true; break; case com.android.internal.R.styleable.View_paddingTop: topPadding = a.getDimensionPixelSize(attr, -1); break; case com.android.internal.R.styleable.View_id: mID = a.getResourceId(attr, NO_ID); } }在这里,从构造方法中用到了两个东西:(1)参数 AttributeSet attrs (2)属性com.android.internal.R.styleable.View 然后就是解析判断赋值了。那么我们先看第一 构造方法参数 attrs是什么东西呢?下面我们通过一个MyTextView来说明:
public class MyTextView extends TextView {public MyTextView(Context context) {this(context, null);}public MyTextView(Context context, AttributeSet attrs) {this(context, attrs, 0);// TODO 自动生成的构造函数存根}public MyTextView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);for (int i = 0; i < attrs.getAttributeCount(); i++) {String name = attrs.getAttributeName(i);String value = attrs.getAttributeValue(i);Log.i("name-value", name + " :" + value);}}}
activity_main.xml 布局文件代码如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xiaotang="http://schemas.android.com/apk/res/com.example.test" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <com.example.test.MyTextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dip" xiaotang:mabc="abc" xiaotang:mcolor="@string/hello_world" xiaotang:mtext="this is test" /></RelativeLayout>我们看到输出结果为:
看到没attrs 其实就是咱在定义xml中定义的属性.通过观察还可以发现,是不是 id获取的为@XXX,没有得到正确的数值,这是因为id为引用类型,需要经过两次处理,或者用TypedArray来处理(后面还会重点提到).
那么com.android.internal.R.styleable.View 是什么鬼呢?其实知道自定义属性的几个步骤的,就知道其中有一步是在attrs.xml中申明 自定义属性:
<resources> <declare-styleable name="mytv"> <attr name="android:text"></attr> <attr name="mtext" format="string" /> <attr name="mcolor" format="reference" /> </declare-styleable> <attr name="mabc" format="string"></attr></resources>
比如说 name="mytv" 通过declare-styleable来申明的,会在R.java文件中,定义如下类属性:
public static final class styleable { public static final int[] mytv = { 0x0101014f, 0x7f010000, 0x7f010001 }; public static final int mytv_android_text = 0; public static final int mytv_mcolor = 2; public static final int mytv_mtext = 1; };可以看到R.java中定义静态属性的特征,定义一个 mytv数组。如果没有通过 declare-styleable来申明,则需要自己来处理成这种数组形式了。那么com.android.internal.R.styleable.View引用的就是一个名字为 View的数组呗,所以一定在某个attrs.xml文件中定义了 <declare-styleable name="View">以及在Android的某个位置有R.java中包含 R.styleable.View,这些都是系统定义好的东西, 在sdk中 \sdk\platforms\android-19\data\res\values 我这是SDK 19,里面就有attrs.xml文件,通过查看可以看到如下定义:
<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" /> <!-- Sets the padding, in pixels, of the left edge; see {@link android.R.attr#padding}. --> <attr name="paddingLeft" format="dimension" /> <!-- Sets the padding, in pixels, of the top edge; see {@link android.R.attr#padding}. --> <attr name="paddingTop" format="dimension" /> <!-- Sets the padding, in pixels, of the right edge; see {@link android.R.attr#padding}. --> <attr name="paddingRight" format="dimension" /> <!-- Sets the padding, in pixels, of the bottom edge; see {@link android.R.attr#padding}. --> <attr name="paddingBottom" format="dimension" /> <!-- Sets the padding, in pixels, of the start edge; see {@link android.R.attr#padding}. --> <attr name="paddingStart" format="dimension" /> <!-- Sets the padding, in pixels, of the end edge; see {@link android.R.attr#padding}. --> <attr name="paddingEnd" format="dimension" />此处只是粘贴了小部分View的定义,是不是看到了里面关于View组件的系统属性定义了!哈哈,看到了系统属性定义,那么自定义属性的操作也就差不多罗!
看到了系统自定义属性,我们再回过头来看看 View的构造方法中这样一行代码:
TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View, defStyleAttr, 0);传递了attrs(我们在xml中使用到的属性),com.android.internal.R.styleable.View 系统给View定义的属性,那么这个操作时干嘛呢?其实猜也猜的出来了,无非就是将attrs中的属性值整合到系统属性中,如果没有,则取默认值!
自定义属性
步骤:
(1)编写values/attrs.xml文件,在里面编写styleable和item元素标签
(2)在布局文件中,定义 命名空间和使用自定义属性
(3)在自定义View的构造方法中使用TypedArray解析自定义属性
下面我们一一讲解这些步骤的用法,对于步骤(1),使用代码如下:
<?xml version="1.0" encoding="UTF-8"?><resources> <declare-styleable name="mytext"> <attr name="mtext" format="string" /> <attr name="mColor" format="reference" /> <attr name="android:text"/></attr> </declare-styleable></resources>在values下面新建 attrs.xml文件,添加declare-styleable申明,可以添加自定义属性,也可以是系统属性赋值于新的含义,通过看有没有format属性判断。上面也提到过,申明了declare-styleable会在R.java文件中生成如下代码:
public static final class styleable { public static final int[] mytext = { 0x0101014f, 0x7f010000, 0x7f010001 }; public static final int mytext_android_text = 0; public static final int mytext_mColor = 2; public static final int mytext_mtext = 1; };
public MyText(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);TypedArray typeArray = context.obtainStyledAttributes(attrs,R.styleable.mytext);String text = typeArray.getString(R.styleable.mytext_mtext);int color = typeArray.getColor(R.styleable.mytext_mColor, 0xf00);this.setText(text);this.setBackgroundColor(color);}通过 R.styleable.mytext,R.styleable.mytext_mtext来引用自定义的属性.当然如果我们没有在attrs.xml中使用declare-styleable申明时,而是如下:
<?xml version="1.0" encoding="UTF-8"?><resources> <attr name="mtitle" format="string"/> <attr name="mage" format="integer"/></resources>那么这样时,我们就需要在自定义View中自己定义数组了,因为context.obtainStyledAttributes()参数中需要传递数组。代码如下:
public class MyText extends TextView {private int attrsId[] = {R.attr.mage,R.attr.mtitle};public MyText(Context context) {this(context, null);}public MyText(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MyText(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);TypedArray typeArray = context.obtainStyledAttributes(attrs,attrsId);int age=typeArray.getInt(0, 0); //0 代表 attrsId索引的值String title = typeArray.getString(1);}
这里还需要提高一个东西就是 TypedArray和AttributeSet的区别:前面也已经提高过,AttributeSet能够获取布局文件中所有的参数和值的,但是引用类型的内容时获取不了的,比如:
android:text="@string/text" text引用strings.xml文件中的内容是不能一步获取到的,就需要使用TypedArray了,具体操作如上。
我们再来看看布局文件中使用自定义属性的用法吧:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xiaotang="http://schemas.android.com/apk/res/com.example.test" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.example.test.MyText android:id="@+id/mytext" android:layout_width="200dip" android:layout_height="100dip" xiaotang:mColor="@color/mycolor" xiaotang:mtext="fdsafdsas" /></LinearLayout>
在布局文件中申明命名空间 xmlns:xiaotang=http://schemas.android.com/apk/res/包名,然后就可以调用了自定义属性啦!
到这里,我们自定义属性就讨论完了。欢迎大家和我讨论学习,一起提高哦!
0 0
- Android自定义控件 自定义属性
- Android自定义view自定义属性
- Android 自定义控件 自定义属性
- Android自定义View-自定义属性
- android 自定义控件自定义属性
- Android自定义View-自定义属性
- android 自定义控件属性
- android自定义属性
- Android自定义属性
- android 里自定义属性
- android自定义属性
- Android自定义控件属性
- Android 中自定义属性
- Android自定义属性
- android 自定义控件属性
- android自定义属性
- android 自定义xml属性
- android使用自定义属性
- armv6、armv7、armv7s、arm64这样四种的区别
- Python实战小程序——字符串
- 数据结构之线性结构---队列 链式储存
- 爬取Ip地址对应的物理位置等信息-百度服务器
- C2039“mem_fun”: 不是“std”的成员
- Android 自定义属性
- datatable 表格属性包括翻页,自己定义
- Linux 下使用 ssh 登录局域网其他电脑的方法
- 宏定义的黑魔法 - 宏菜鸟起飞手册
- input输入框限制输入字节数
- JMockit的主要注解
- mysql
- (1)Java内存回收
- TensorFlow Android Camera Demo(Ubuntu Trusty 14.04 LTS)