Android自定义View专题三-自定义View属性

来源:互联网 发布:新发行的人工智能基金 编辑:程序博客网 时间:2024/06/15 17:51

目录

    • 目录
    • 前言
    • 实例
    • 在XML文件中导入属性集的两种方法
      • 1 方法一
      • 2 方法二
    • 获取定义属性的所有方法
    • declare-styleable标签其它属性用法
    • AttributeSet与TypedArray 详解

版权声明:本文为博主原创文章,未经博主允许不得转载。

1.前言

写这篇博客主要是为了我的下一篇博客做准备,由于下一篇博客里面用到了自定义属性,我想在这里还是给大家讲解以下比较好。同时也用到了自定义view的其它知识点,但是都比较简单。这里就着重介绍一下自定义View属性。

编写自定义View主要有以下几个步骤:1)自定义一个MyView需要继承View类2)在Values文件夹下面创建attrs.xml文件3)在布局文件中使用自定义的属性,需要注意前面的命名空间4)在MyView的构造方法中获取这些属性。

光说不练假把式,下面我们就通过代码的方式来介绍自定义View属性的使用。

2.实例

通过代码可以更好的说明自定义属性的用法

* 自定义View类

    public class MyView extends View {    private float textSize;    private int textColor;    public MyView(Context context) {        this(context,null);    }    public MyView(Context context, @Nullable AttributeSet attrs) {        this(context, attrs,0);    }    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyView);        textSize = typedArray.getDimension(R.styleable.VoteView_myTextSize, -1);        textColor = typedArray.getColor(R.styleable.VoteView_myTextColor, -1);        System.out.println("textSize:"+textSize+"textColor:"+textColor);        typedArray.recycle();    }}

这里需要注意的一点是必须在最后调用TypedArray的recycle()方法,用来释放资源

  • 自定义View属性

    <declare-styleable name="MyView"><attr name="MySize" format="dimension" /><attr name = "MyColor" format = "color" />

  • 布局文件

3.在XML文件中导入属性集的两种方法

3.1 方法一

首先在根布局上加上xmlns:shi ="http://schemas.android.com/apk/res/com.shi.mychat2" 

这里有两点需要注意的地方

1.xmlns:shi,这里的shi是自定义的,你想定义成什么就可以定义成什么。但要注意的是,下面访问你定义的XML控件属性时,就是通过这个标识符访问的。比如我们这里定义成shi;那我们下面对应的访问自定义:shi:MySize="@dimen/tensp"2、最后的:com.shi.mychat2,是AndroidManifest.xml中的包名。即AndroidManifest.xml中package字段对应的值,如下所示:

3.2 方法二

另一种自动导入自定义属性集的方式要相对简单,要根布局控件上添加:xmlns:shi="http://schemas.android.com/apk/res-auto"  这里面的含义和上面的一样。

读到这里我们应该明白,为什么我们没有导入属性集也能使用自定义属性,那是因为我们用到的Support中的控件也用到了自定义属性,已经事先导入过了 xmlns:app=”http://schemas.android.com/apk/res-auto”。如果没有用到Support包中的控件还需要自己手动的导入。

4.获取定义属性的所有方法

使用代码获取某个属性用户所定义的值,主要是使用TypedArray类,这个类担供了所有的获取某个属性值的方法,

typedArray.getInt(int index, float defValue);  typedArray.getDimension(int index, float defValue);  typedArray.getBoolean(int index, float defValue);  typedArray.getColor(int index, float defValue);  typedArray.getString(int index)  typedArray.getDrawable(int index);  typedArray.getResources();  

5.declare-styleable标签其它属性用法

1、 reference:参考某一资源ID。

(1)属性定义:

<declare-styleable name = "名称">         <attr name = "background" format = "reference" />  </declare-styleable>  

(2)属性使用:

<ImageView          android:layout_width = "42dip"          android:layout_height = "42dip"          android:background = "@drawable/图片ID"/>  

2. color:颜色值。

(1)属性定义:

<declare-styleable name = "名称">         <attr name = "textColor" format = "color" />  </declare-styleable>  

(2)属性使用:

<TextView           android:layout_width = "42dip"           android:layout_height = "42dip"           android:textColor = "#00FF00"/>  

3. boolean:布尔值。

(1)属性定义:

<declare-styleable name = "名称">         <attr name = "focusable" format = "boolean" />  </declare-styleable>  

(2)属性使用:

<Button          android:layout_width = "42dip"          android:layout_height = "42dip"          android:focusable = "true"/>  

4. dimension:尺寸值。

(1)属性定义:

<declare-styleable name = "名称">         <attr name = "layout_width" format = "dimension" />  </declare-styleable>  

(2)属性使用:

<Button          android:layout_width = "42dip"          android:layout_height = "42dip"/>  

5. float:浮点值。

(1)属性定义:

<declare-styleable name = "AlphaAnimation">         <attr name = "fromAlpha" format = "float" />         <attr name = "toAlpha" format = "float" />  </declare-styleable>  

(2)属性使用:

<alpha         android:fromAlpha = "1.0"         android:toAlpha = "0.7"/>  

6. integer:整型值。

(1)属性定义:

<declare-styleable name = "AnimatedRotateDrawable">         <attr name = "visible" />         <attr name = "frameDuration" format="integer" />         <attr name = "framesCount" format="integer" />         <attr name = "pivotX" />         <attr name = "pivotY" />         <attr name = "drawable" />  </declare-styleable>  

(2)属性使用:

<animated-rotate         xmlns:android = "http://schemas.android.com/apk/res/android"          android:drawable = "@drawable/图片ID"          android:pivotX = "50%"          android:pivotY = "50%"          android:framesCount = "12"          android:frameDuration = "100"/>  

7. string:字符串。

(1)属性定义:

<declare-styleable name = "MapView">         <attr name = "apiKey" format = "string" />  </declare-styleable>  

(2)属性使用:

<com.google.android.maps.MapView         android:layout_width = "fill_parent"         android:layout_height = "fill_parent"         android:apiKey = "0jOkQ80oD1JL9C6HAja99uGXCRiS2CGjKO_bc_g" />  
  1. fraction:百分数。

(1)属性定义:

<declare-styleable name="RotateDrawable">        <attr name = "visible" />        <attr name = "fromDegrees" format = "float" />        <attr name = "toDegrees" format = "float" />        <attr name = "pivotX" format = "fraction" />        <attr name = "pivotY" format = "fraction" />        <attr name = "drawable" />  </declare-styleable>  

(2)属性使用:

<rotate        xmlns:android = "http://schemas.android.com/apk/res/android"       android:interpolator = "@anim/动画ID"        android:fromDegrees = "0"       android:toDegrees = "360"        android:pivotX = "200%"        android:pivotY = "300%"       android:duration = "5000"        android:repeatMode = "restart"        android:repeatCount = "infinite"/>  

9. enum:枚举值。

(1)属性定义:

<declare-styleable name="名称">        <attr name="orientation">               <enum name="horizontal" value="0" />               <enum name="vertical" value="1" />        </attr>             </declare-styleable>  

(2)属性使用:

<LinearLayout          xmlns:android = "http://schemas.android.com/apk/res/android"          android:orientation = "vertical"          android:layout_width = "fill_parent"          android:layout_height = "fill_parent">  </LinearLayout>  

10. flag:位或运算。

(1)属性定义:

<declare-styleable name="名称">         <attr name="windowSoftInputMode">                 <flag name = "stateUnspecified" value = "0" />                 <flag name = "stateUnchanged" value = "1" />                 <flag name = "stateHidden" value = "2" />                 <flag name = "stateAlwaysHidden" value = "3" />                 <flag name = "stateVisible" value = "4" />                 <flag name = "stateAlwaysVisible" value = "5" />                 <flag name = "adjustUnspecified" value = "0x00" />                 <flag name = "adjustResize" value = "0x10" />                 <flag name = "adjustPan" value = "0x20" />                 <flag name = "adjustNothing" value = "0x30" />          </attr>          </declare-styleable>  

(2)属性使用:

<activity         android:name = ".StyleAndThemeActivity"         android:label = "@string/app_name"         android:windowSoftInputMode = "stateUnspecified | stateUnchanged | stateHidden">         <intent-filter>                <action android:name = "android.intent.action.MAIN" />                <category android:name = "android.intent.category.LAUNCHER" />         </intent-filter>   </activity>  

特别要注意:
属性定义时可以指定多种类型值。

(1)属性定义:

<declare-styleable name = "名称">         <attr name = "background" format = "reference|color" />  </declare-styleable>  

(2)属性使用:

<ImageView          android:layout_width = "42dip"          android:layout_height = "42dip"          android:background = "@drawable/图片ID|#00FF00"/>  

6 AttributeSet与TypedArray 详解

构造方法中的有个参数叫做AttributeSet(eg: MyView(Context context, AttributeSet attrs) )这个参数看名字就知道包含的是参数的集合,那么我能不能通过它去获取我的自定义属性呢?
首先AttributeSet中的确保存的是该View声明的所有的属性,并且外面的确可以通过它去获取(自定义的)属性,怎么做呢?
其实看下AttributeSet的方法就明白了,下面看代码。

public MyView(Context context, AttributeSet attrs) {        super(context, attrs);        int count = attrs.getAttributeCount();        for (int i = 0; i < count; i++) {            String attrName = attrs.getAttributeName(i);            String attrVal = attrs.getAttributeValue(i);            Log.e(TAG, "attrName = " + attrName + " , attrVal = " + attrVal);        }    }

布局

    <com.shi.mychat2.customview.MyView    android:layout_width="100dp"    shi:MySize="10dp"    app:MyColor="#fff"    android:layout_height="100dp" />

输出:

    10-15 17:06:42.518 5870-5870/? I/System.out: attrName = layout_width , attrVal = 100.0dip10-15 17:06:42.518 5870-5870/? I/System.out: attrName = layout_height , attrVal = 100.0dip10-15 17:06:42.518 5870-5870/? I/System.out: attrName = MyColor , attrVal = #ffffffff10-15 17:06:42.518 5870-5870/? I/System.out: attrName = MySize , attrVal = 10.0dip

通过AttributeSet可以获得布局文件中定义的所有属性的key和value(还有一些方法,自己去尝试),那么是不是说TypedArray这个类是否可以不用了呢,答案是否定的。

现在关注下一个问题:

TypedArray是什么鬼?从哪冒出来的,就要我去使用?
我们简单修改下,布局文件中的MyView的属性。

<com.shi.mychat2.customview.MyView    android:layout_width="100dp"    shi:MySize="@dimen/tensp"    app:MyColor="@color/F8f8f8"    android:layout_height="100dp" />

现在再次运行的结果是:

 10-15 17:03:18.148 5470-5470/? I/System.out: attrName = layout_width , attrVal = 100.0dip10-15 17:03:18.148 5470-5470/? I/System.out: attrName = layout_height , attrVal = 100.0dip10-15 17:03:18.148 5470-5470/? I/System.out: attrName = MyColor , attrVal = @213103411210-15 17:03:18.148 5470-5470/? I/System.out: attrName = MySize , attrVal = @2131099845

use typedarray
10-15 17:06:42.518 5870-5870/? I/System.out: attrName = MyColor , attrVal = #ffffffff

发现了什么?通过AttributeSet获取的值,如果是引用都变成了@+数字的字符串。你说,这玩意你能看懂么?那么你看看最后一行使用TypedArray获取的值,是不是瞬间明白了什么。

TypedArray其实是用来简化我们的工作的,比如上例,如果布局中的属性的值是引用类型(比如:@dimen/dp100),如果使用AttributeSet去获得最终的像素值,那么需要第一步拿到id,第二步再去解析id。而TypedArray正是帮我们简化了这个过程。

贴一下:如果通过AttributeSet获取最终的像素值的过程:

int widthDimensionId =  attrs.getAttributeResourceValue(0, -1);        Log.e(TAG, "layout_width= "+getResources().getDimension(widthDimensionId));

参考
启舰
鸿洋

原创粉丝点击