自定义初学4——自定义属性

简介: 前面只是简单说了自定义View,接下来我们再来个增强版——自定义View的属性1、自定义View的属性,首先在res/values/  下建立一个attrs.xml , 在里面定义我们的属性。
前面只是简单说了自定义View,接下来我们再来个增强版——自定义View的属性
1、自定义View的属性,首先在res/values/  下建立一个attrs.xml , 在里面定义我们的属性。

<resources>

    <declare-styleable name="CustomAttrView">
        <attr name="text" format="string" />
        <attr name="textColor" format="color" />
        <attr name="textSize" format="dimension" />
    </declare-styleable>

</resources>

这里简单介绍一下控件的常用属性

 format的取值及使用

1. Reference:引用类型,参考某一资源ID

(1)属性定义:

<declare-styleable name = "名称">
<attr name = "background" format = "reference"/>
<attr name = "src" 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"/>
<attr name = "layout_height" format = "dimension"/>
</declare-styleable>

 

(2)属性使用:

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

 

5. float:浮点值。

(1)属性定义:

<declare-styleable name = "名称">
<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 = "名称">
<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 = "名称">
<attr name = "text" format = "string" /> 
</declare-styleable>

 

(2)属性使用:

<TextView 
android:layout_width = "fill_parent"
android:layout_height = "fill_parent" 
android:text ="0jOkQ80oD1JL9C6HAja99uGXCRiS2CGjKO_bc_g"/>

 


8. fraction:百分数类型。

(1)属性定义:

<declare-styleable name="名称">
<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"/>

  
11. 多类型

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

2、在布局文件中声明我们的View

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.example.activity.view.CustomAttrView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:padding="10dp"
        custom:text="9958"
        custom:textColor="#ff0000"
        custom:textSize="30sp" /> 

这里要强调的一点就是,一定要引入我们自己的名称空间(我绿色标注的部分),后面的包路径指的是项目的包名。

3、在View的构造方法中,获得我们的自定义的属性

public class CustomAttrView extends View {

    private String mStrText;

    private int mTextColor;

    private int mTextSize;

    /**
     * 绘制时控制文本绘制的范围
     */
    private Rect mBound;
    private Paint mPaint;

    public CustomAttrView(Context context) {
        this(context, null);
    }

    public CustomAttrView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);

    }

    // 获得自定义的样式属性
    public CustomAttrView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        /**
         * 获得自定义样式属性
         */
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs,
                R.styleable.CustomAttrView, defStyle, 0);
//        int n = typedArray.getIndexCount();
//        for (int i = 0; i < n; i++) {
//            int attr = typedArray.getIndex(i);
//            switch (attr) {
//            case R.styleable.CustomAttrView_text:
//                mStrText = typedArray.getString(attr);
//                break;
//            case R.styleable.CustomAttrView_textColor:
//                // 默认颜色设置为黑色
//                mTextColor = typedArray.getColor(attr, Color.BLACK);
//                break;
//            case R.styleable.CustomAttrView_textSize:
//                // 默认设置为16sp,TypeValue也可以把sp转化为px
//                mTextSize = typedArray.getDimensionPixelSize(attr,
//                        (int) TypedValue.applyDimension(
//                                TypedValue.COMPLEX_UNIT_SP, 16, getResources()
//                                        .getDisplayMetrics()));
//                break;
//
//            }
//
//        }

        /**
         * 下面三句和上面注释掉的句子的作用一样
         */
        mStrText = typedArray.getString(R.styleable.CustomAttrView_text);
        mTextColor = typedArray.getColor(R.styleable.CustomAttrView_textColor, Color.BLACK);
        mTextSize = typedArray.getDimensionPixelSize(R.styleable.CustomAttrView_textSize,16);
        typedArray.recycle();

        mPaint = new Paint();
        mPaint.setTextSize(mTextSize);
         mPaint.setColor(mTextColor);
/**
         * 获得绘制文本的宽和高
         */

        mBound = new Rect();
        mPaint.getTextBounds(mStrText, 0, mStrText.length(), mBound);

    }
}

 

4、重写onDraw,调用系统提供的onMesure方法
@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
    protected void onDraw(Canvas canvas) {
        mPaint.setColor(Color.BLUE);
        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);

        mPaint.setColor(mTextColor);
        canvas.drawText(mStrText, getWidth() / 2 - mBound.width() / 2,
                getHeight() / 2 + mBound.height() / 2, mPaint);
    }

此时效果如下:

但是此时如果我们把布局文件的宽和高写成wrap_content,会发现效果和我们想的并不一样:


这是因为系统帮我们测量的高度和宽度都是MATCH_PARNET,当我们设置明确的宽度和高度时,系统帮我们测量的结果就是我们设置的结果,当我们设置为WRAP_CONTENT或者MATCH_PARENT系统帮我们测量的结果就是MATCH_PARENT的长度。

所以,当设置了WRAP_CONTENT时,我们需要自己进行测量,即重写onMesure方法,重写之前先了解下MeasureSpec的specMode的类型:

EXACTLY:一般是设置了明确的值或者是MATCH_PARENT

AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT

UNSPECIFIED:表示子布局想要多大就多大,很少使用

下面是我们重写onMeasure代码:


@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int width = 0;
        int height = 0;

        /**
         * 设置宽度
         */
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec); 
        switch (specMode) {
        case MeasureSpec.EXACTLY:// 明确指定了
            width = getPaddingLeft() + getPaddingRight() + specSize;
            break;
        case MeasureSpec.AT_MOST:// 一般为WARP_CONTENT
            width = getPaddingLeft() + getPaddingRight() + mBound.width();
            break;
        }

        /**
         * 设置高度
         */
        specMode = MeasureSpec.getMode(heightMeasureSpec);
        specSize = MeasureSpec.getSize(heightMeasureSpec);
        switch (specMode) {
        case MeasureSpec.EXACTLY:// 明确指定了
            height = getPaddingTop() + getPaddingBottom() + specSize;
            break;
        case MeasureSpec.AT_MOST:// 一般为WARP_CONTENT
            height = getPaddingTop() + getPaddingBottom() + mBound.height();
            break;
        }

        setMeasuredDimension(width, height);

    }

现在我们可以对高度、宽度进行随便的设置了,基本可以满足我们的需求。

当然了我们这个自定义View与TextView相比还没什么区别,但是前面的例子已经提到,我们可以给View添加一些监听事件,代码就不写了,想看的话可以下载源码。


源代码


参考:


相关文章
|
5月前
Thymeleaf内置对象、定义变量、URL参数及标签自定义属性
Thymeleaf内置对象、定义变量、URL参数及标签自定义属性
109 0
|
2月前
|
JavaScript 前端开发 API
【每周一个小技巧】如何自定义客服、生活号组件的样式
【每周一个小技巧】如何自定义客服、生活号组件的样式
21 2
|
8月前
|
缓存 JavaScript
Vue常用属性(计算属性和侦听器属性)
Vue常用属性(计算属性和侦听器属性)
自定义标签属性
自定义标签属性
44 0
|
Java 开发工具 Windows
五、实现自定义配置属性动态加载
在我们日常开发项目时,经常需要自定义一些配置属性用于我们项目的一些启动配置,这里我们就直接在application-dev配置文件中直接实现一下自定义配置属性的读取与使用,便于我们在dev和prod配置文件来回切换。
71 0
五、实现自定义配置属性动态加载
|
Java 开发者
自定义框架_属性设置 | 学习笔记
快速学习自定义框架_属性设置,介绍了自定义框架_属性设置系统机制, 以及在实际应用过程中如何使用。
65 0
|
JavaScript 开发者
veu 中通过属性绑定为元素设置 class 类样式 | 学习笔记
快速学习 veu 中通过属性绑定为元素设置 class 类样式
124 0
veu  中通过属性绑定为元素设置 class 类样式  |  学习笔记
自定义大头针
自定义大头针
180 0
自定义大头针
|
Java 开发者
自定义标签之带有属性的标签 | 学习笔记
快速学习自定义标签之带有属性的标签