android 自定义控件属性

控件属性想必大家都知道如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <com.example.customview.CustomView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#000000"
         />
</RelativeLayout>

上面的xml文件中 android:layout_width,android:layout_height就是系统的控件属性,加入我把xmlns:android这个改成xmlns:androidtag呢?

发现它下面使用到的属性就会报错,        ‘layout_height‘ attribute should be definedless...意思是说你layout_height这个属性没有被定义,首先要明白xmlns是什么意思

xmlns是XML Namespaces的缩写,中文名称是XML命名空间。使用的规则为,首先定义命名空间xmlns:namespaceprefix="namespaceURI"。Android中xml中的使用是:

xmlns:前缀=http://schemas.android.com/apk/res/应用程序包路径;然后使用的时候按格式:namespaceprefix(缀):属性

如果使用xmlns,则xmlns的定义必须放在最外层开始的的标记中

当命名空间被定义之后,所有带有相同前缀的子元素都会与同一个命名空间相关联。避免XML解析器对xml解析时的发送名字冲突,这就是使用xmlns的必要性。当自定义的View有自己的属性的时候,就用到xmlns来定义一个命名空间

所以我们把xmlns:android改成了xmlns:androidtag为什么导致报错,然后为什么我们创建一个布局xml文件就会自动给我们这些数据呢?比如android:layout_width,这是因为系统给我们定义好了这些属性,如何查看系统给的属性呢?E:\soft\Android-SDK\platforms\android-19\data\res
 这是我的sdk放在e盘的,

这些都是系统给我们自带好的一些资源,比如弹一个toast,它的背景资源就是在drawable目录下,哪我们自定义控件属性要放在哪呢?我们在res目录下有个attrs文件:

这里面定义了很多关于文字,颜色,id,尺寸等资源,而系统自定义的属性就是存放在attrs文件里,打开看一眼,

我们看下它怎么定义的,首先<declare-styleable name="View"> 这其中有二个属性名称,

declare-styleable属性是声明表示你要自定义控件属性,

name表示你要自定义控件属性的名称,如上面的name="View"表示给控件View要定义属性

attr
表示定义属性的名称

format表示改属性名称对应的值,而且format对应的值有二个如

<attr
name="background" format="reference|color" /> 这个是给view设置背景的属性,取值为reference|color,其中reference表示可以引用res下的资源,比如可以是colors.xml文件中定义的一个颜色值,也可以是一个图片,也可以是drawable文件夹下的一个定义的背景xml文件,color表示是直接写的值
比如“#ffffff”就是给背景设置白色,

哪我们根据系统自己模仿也在res/values下创建一个attrs文件,

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomView">
        <attr name="text" format="reference|string"></attr>
    </declare-styleable>
</resources>

这个是表示你给CustomView控件设置了一个text属性,但是如何在xml布局文件中使用呢?它不是我们系统给定的属性直接使用android:text即可,

在xml要使用自定义的属性必须要先声明命名空间,系统的命名空间是:

xmlns:android="http://schemas.android.com/apk/res/android"

android这个前缀被系统使用了,我们就不能再使用android作为前缀了,比如前缀为customview,还有就是要导入自定义的属性集,一般有二种做法

1:

xmlns:android="http://schemas.android.com/apk/res/com.example.customview"

我们看到res/后面不在是android 而是我们自己应用的包名,

2:

xmlns:android="http://schemas.android.com/apk/res-auto"

这二种方法都行,

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:customview="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <com.example.customview.CustomView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        customview:text="美丽新世界"
         />
</RelativeLayout>

现在问题是这些属性不是系统的属性,我们如何通过代码获取呢?

使用代码获取某个属性用户所定义的值,主要是使用TypedArray类,这个类担供了所有的获取某个属性值的方法,如下所示,但需要注意的是,在使用完以后必须调用TypedArray的recycle()方法,用来释放资源

我们在CustomView类的构造函数中来获取自定义的属性值并绘制显示在屏幕上:

package com.example.customview;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
/**
 * Created by admin on 2016/5/9.
 */
public class CustomView extends View {
    private static final String TAG ="CustomView" ;
    private Paint mPaint = null;
    String content ;
    public CustomView(Context context) {
        super(context);
    }
    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint();
        TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.CustomView);
        content = typedArray.getString(R.styleable.CustomView_text);
        typedArray.recycle();//释放资源
    }
    public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setTextSize(60);//设置文字大小
        canvas.drawText(content,100,100,mPaint);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

如图:

我们可以看下系统是怎么获取系统的属性值的:

public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    this(context);

    final TypedArray a = context.obtainStyledAttributes(
            attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);

    if (mDebugViewAttributes) {
        saveAttributeData(attrs, a);
    }

    Drawable background = null;

    int leftPadding = -1;
    int topPadding = -1;
    int rightPadding = -1;
    int bottomPadding = -1;
    int startPadding = UNDEFINED_PADDING;
    int endPadding = UNDEFINED_PADDING;

    int padding = -1;

    int viewFlagValues = 0;
    int viewFlagMasks = 0;

    boolean setScrollContainer = false;

    int x = 0;
    int y = 0;

    float tx = 0;
    float ty = 0;
    float tz = 0;
    float elevation = 0;
    float rotation = 0;
    float rotationX = 0;
    float rotationY = 0;
    float sx = 1f;
    float sy = 1f;
    boolean transformSet = false;

    int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
    int overScrollMode = mOverScrollMode;
    boolean initializeScrollbars = false;
    boolean initializeScrollIndicators = false;

    boolean startPaddingDefined = false;
    boolean endPaddingDefined = false;
    boolean leftPaddingDefined = false;
    boolean rightPaddingDefined = false;

    final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;

    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_paddingRight:
                rightPadding = a.getDimensionPixelSize(attr, -1);
                mUserPaddingRightInitial = rightPadding;
                rightPaddingDefined = true;
                break;

这只是系统类View的一部分构造函数中的代码,它是如何获取属性值的,没事可以看看,

我们可以看下TypedArray类给我们提供了哪些方法可以获取属性值

declare-styleable标签其它属性用法

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

(1)属性定义:

[html] view
plain
 copy

  1. <declare-styleable name = "名称">
  2. <attr name = "background" format = "reference" />
  3. </declare-styleable>

(2)属性使用:

[html] view
plain
 copy

  1. <ImageView
  2. android:layout_width = "42dip"
  3. android:layout_height = "42dip"
  4. android:background = "@drawable/图片ID"/>

2. color:颜色值。

(1)属性定义:

[html] view
plain
 copy

  1. <declare-styleable name = "名称">
  2. <attr name = "textColor" format = "color" />
  3. </declare-styleable>

(2)属性使用:

[html] view
plain
 copy

  1. <TextView
  2. android:layout_width = "42dip"
  3. android:layout_height = "42dip"
  4. android:textColor = "#00FF00"/>

3. boolean:布尔值。

(1)属性定义:

[html] view
plain
 copy

  1. <declare-styleable name = "名称">
  2. <attr name = "focusable" format = "boolean" />
  3. </declare-styleable>

(2)属性使用:

[html] view
plain
 copy

  1. <Button
  2. android:layout_width = "42dip"
  3. android:layout_height = "42dip"
  4. android:focusable = "true"/>

4. dimension:尺寸值。

(1)属性定义:

[html] view
plain
 copy

  1. <declare-styleable name = "名称">
  2. <attr name = "layout_width" format = "dimension" />
  3. </declare-styleable>

(2)属性使用:

[html] view
plain
 copy

  1. <Button
  2. android:layout_width = "42dip"
  3. android:layout_height = "42dip"/>

5. float:浮点值。

(1)属性定义:

[html] view
plain
 copy

  1. <declare-styleable name = "AlphaAnimation">
  2. <attr name = "fromAlpha" format = "float" />
  3. <attr name = "toAlpha" format = "float" />
  4. </declare-styleable>

(2)属性使用:

[html] view
plain
 copy

  1. <alpha
  2. android:fromAlpha = "1.0"
  3. android:toAlpha = "0.7"/>

6. integer:整型值。

(1)属性定义:

[html] view
plain
 copy

  1. <declare-styleable name = "AnimatedRotateDrawable">
  2. <attr name = "visible" />
  3. <attr name = "frameDuration" format="integer" />
  4. <attr name = "framesCount" format="integer" />
  5. <attr name = "pivotX" />
  6. <attr name = "pivotY" />
  7. <attr name = "drawable" />
  8. </declare-styleable>

(2)属性使用:

[html] view
plain
 copy

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

7. string:字符串。

(1)属性定义:

[html] view
plain
 copy

  1. <declare-styleable name = "MapView">
  2. <attr name = "apiKey" format = "string" />
  3. </declare-styleable>

(2)属性使用:

[html] view
plain
 copy

  1. <com.google.android.maps.MapView
  2. android:layout_width = "fill_parent"
  3. android:layout_height = "fill_parent"
  4. android:apiKey = "0jOkQ80oD1JL9C6HAja99uGXCRiS2CGjKO_bc_g" />

8. fraction:百分数。

(1)属性定义:

[html] view
plain
 copy

  1. <declare-styleable name="RotateDrawable">
  2. <attr name = "visible" />
  3. <attr name = "fromDegrees" format = "float" />
  4. <attr name = "toDegrees" format = "float" />
  5. <attr name = "pivotX" format = "fraction" />
  6. <attr name = "pivotY" format = "fraction" />
  7. <attr name = "drawable" />
  8. </declare-styleable>

(2)属性使用:

[html] view
plain
 copy

  1. <rotate
  2. xmlns:android = "http://schemas.android.com/apk/res/android"
  3.      android:interpolator = "@anim/动画ID"
  4. android:fromDegrees = "0"
  5.      android:toDegrees = "360"
  6. android:pivotX = "200%"
  7. android:pivotY = "300%"
  8.      android:duration = "5000"
  9. android:repeatMode = "restart"
  10. android:repeatCount = "infinite"/>

9. enum:枚举值。

(1)属性定义:

[html] view
plain
 copy

  1. <declare-styleable name="名称">
  2. <attr name="orientation">
  3. <enum name="horizontal" value="0" />
  4. <enum name="vertical" value="1" />
  5. </attr>
  6. </declare-styleable>

(2)属性使用:

[html] view
plain
 copy

  1. <LinearLayout
  2. xmlns:android = "http://schemas.android.com/apk/res/android"
  3. android:orientation = "vertical"
  4. android:layout_width = "fill_parent"
  5. android:layout_height = "fill_parent">
  6. </LinearLayout>

10. flag:位或运算。

(1)属性定义:

[html] view
plain
 copy

  1. <declare-styleable name="名称">
  2. <attr name="windowSoftInputMode">
  3. <flag name = "stateUnspecified" value = "0" />
  4. <flag name = "stateUnchanged" value = "1" />
  5. <flag name = "stateHidden" value = "2" />
  6. <flag name = "stateAlwaysHidden" value = "3" />
  7. <flag name = "stateVisible" value = "4" />
  8. <flag name = "stateAlwaysVisible" value = "5" />
  9. <flag name = "adjustUnspecified" value = "0x00" />
  10. <flag name = "adjustResize" value = "0x10" />
  11. <flag name = "adjustPan" value = "0x20" />
  12. <flag name = "adjustNothing" value = "0x30" />
  13. </attr>
  14. </declare-styleable>

(2)属性使用:

[html] view
plain
 copy

  1. <activity
  2. android:name = ".StyleAndThemeActivity"
  3. android:label = "@string/app_name"
  4. android:windowSoftInputMode = "stateUnspecified | stateUnchanged | stateHidden">
  5. <intent-filter>
  6. <action android:name = "android.intent.action.MAIN" />
  7. <category android:name = "android.intent.category.LAUNCHER" />
  8. </intent-filter>
  9. </activity>

特别要注意:

属性定义时可以指定多种类型值。

(1)属性定义:

[html] view
plain
 copy

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

(2)属性使用:

[html] view
plain
 copy

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

注:最后这些属性这么使用来自http://blog.csdn.net/harvic880925/article/details/46537767,因为写起来实在太费时间,感谢博主!

时间: 2024-10-11 00:04:55

android 自定义控件属性的相关文章

android自定义控件属性

有两种方法为自定义的控件设置属性 . 来自为知笔记(Wiz) android自定义控件属性,布布扣,bubuko.com

android 自定义控件属性(TypedArray以及attrs解释)

最近在捣鼓android 自定义控件属性,学到了TypedArray以及attrs.在这其中看了一篇大神博客Android 深入理解Android中的自定义属性.我就更加深入学习力一番.我就沿着这个学习,讲一下流程吧,后续一篇还有应用. 1.attrs文件编写 <?xml version="1.0" encoding="utf-8"?> <resources> <attr name="titleText" forma

Android自定义控件属性的使用

1. reference:参考某一资源ID. (1)属性定义: <declare-styleable name = "名称"> <attr name = "background" format = "reference" /> </declare-styleable> (2)属性使用: <ImageView android:layout_width = "42dip" android:

Android自定义控件皮肤

Android自定义控件皮肤 对于Android的自带控件,其外观只能说中规中矩,而我们平时所看到的Android应用中,一个简单的按钮都做得十分美观,甚至于许多按钮在按下时的外观都有一定变化,用户体验十分好.这其中,就涉及到了Android自定义控件属性的操作方法,以下操作以实现自定义按钮皮肤为例. 1. 我们要自定义将要实现的外观状态,可以是图片或者是自定义的xml,这是我们直接自定义不同状态的颜色xml,在values目录下新建colors.xml,代码如下: colors.xml <?x

自定义控件属性的获取

在资源文件目录下新建attrs.xml文件,声明需要的属性 <?xml version="1.0" encoding="utf-8"?> <resources><!-- resource是跟标签,可以在里面定义若干个declare-styleable --> <declare-styleable name="custom_view"><!-- name定义了变量的名称 --> <a

【android自定义控件】自定义View属性

1.自定义View的属性 2.在View的构造方法中获得我们自定义的属性 3.重写onMesure 4.重写onDraw 3这个步骤不是必须,当然了大部分情况下还是需要重写的. 1.自定义View的属性,首先在res/values/  下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式. <?xml version="1.0" encoding="utf-8"?> <resources> <attr name=&

Android自定义控件之自定义组合控件(三)

前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发成本,以及维护成本. 使用自定义组合控件的好处? 我们在项目开发中经常会遇见很多相似或者相同的布局,比如APP的标题栏,我们从三种方式实现标题栏来对比自定义组件带来的好处,毕竟好的东西还是以提高开发效率,降低开发成本为导向的. 1.)第一种方式:直接在每个xml布局中写相同的标题栏布局代码 <?xm

android 自定义控件---圆形方向盘

在做Android平台开发的时候,经常会遇到安卓原生控件无法满足需求的情况,安卓允许开发者去继承已经存在的控件或者实现你自己的控件. 先来看一下效果图 采用直接集成View类,重写onDrow方法绘制. 下面附上主要代码. 1 新建一个类CircleView 继承自View 1 package com.lennon.view; 2 3 import android.content.Context; 4 import android.graphics.Canvas; 5 import androi

Android自定义控件_View的绘制流程

每一个View/ViewGroup的显示都会经过三个过程:1.measure过程(测量View显示的大小,位置):2.layout过程(布局view的位置):3.draw过程(上一篇文章说到的通过canvas绘制到界面上显示,形成了各色的View) 下面分析一下各个过程:measure过程: 因为DecorView实际上是派生自FrameLayout的类,也即一个ViewGroup实例,该ViewGroup内部的ContentViews又是一个ViewGroup实例,依次内嵌View或ViewG