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

目录

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

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.0dip
10-15 17:06:42.518 5870-5870/? I/System.out: attrName = layout_height , attrVal = 100.0dip
10-15 17:06:42.518 5870-5870/? I/System.out: attrName = MyColor , attrVal = #ffffffff
10-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.0dip
10-15 17:03:18.148 5470-5470/? I/System.out: attrName = layout_height , attrVal = 100.0dip
10-15 17:03:18.148 5470-5470/? I/System.out: attrName = MyColor , attrVal = @2131034112
10-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));

参考
启舰
鸿洋

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值