Android自定义控件之自定义属性(二)

yizhihongxing

Android自定义控件之自定义属性(二)主要涉及到在自定义控件中自定义属性的使用方法,其完整攻略如下:

1. 前言

在Android中,自定义View是非常常见的需求,而自定义控件之一的自定义属性,也是比较重要的一部分,通过自定义属性,我们可以方便地在XML文件中设置控件的属性,这样可以大大提高我们的开发效率。在之前的博客中,我们已经学习了如何自定义属性,但是那次只是介绍了自定义属性的基本用法,这次我们会更深入地学习如何在自定义控件中使用自定义属性。

2. 自定义属性的使用

2.1 属性声明

在创建自定义属性之前,需要在res/values/attrs.xml文件中进行属性的声明。如:

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

上面的代码中,我们定义了一个叫做MyCustomView的样式,其中包含了三个属性:

  1. textColor:字体颜色,属性类型为color。
  2. textSize:字体大小,属性类型为dimension。
  3. text:显示的文本,属性类型为string。

其中,name表示属性的名称,format表示属性的值类型。format主要有以下选择:

  1. reference:引用类型,用@符号指定资源ID,如@drawable/my_bg。

  2. color:颜色类型,用#符号指定颜色,如#FF0000。

  3. dimension:尺寸类型,如10dp, 20sp等。

  4. float:浮点数类型,如3.14。

  5. boolean:布尔类型,如true或false。

2.2 在布局文件中使用

在Activity的布局文件中使用自定义属性时,只需要加上自定义命名空间,例如:

<com.example.view.MyCustomView
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"   
    custom:textColor="#FF0000"
    custom:textSize="20sp"
    custom:text="hello, world!"/>

其中的xmlns:custom="http://schemas.android.com/apk/res-auto"是必须的,这样才能使用自定义命名空间。

2.3 在代码中获取属性值

在自定义控件中获取自定义属性的值,需要重写View的构造函数,如:

public class MyCustomView extends View {

    private int textColor;
    private float textSize;
    private String text;

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

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

    public MyCustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView);
        textColor = ta.getColor(R.styleable.MyCustomView_textColor, Color.BLACK);
        textSize = ta.getDimension(R.styleable.MyCustomView_textSize, 16);
        text = ta.hasValue(R.styleable.MyCustomView_text) ? ta.getString(R.styleable.MyCustomView_text) : "";
        ta.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint();
        paint.setColor(textColor);
        paint.setTextSize(textSize);
        canvas.drawText(text, 50, 50, paint);
    }
}

在代码中,我们通过调用Context的obtainStyledAttributes方法获取TypedArray来获取属性值,这个方法的参数有两个:

  • AttributeSet attrs:继承View的子类一般都会有三个参数的构造方法,其中第二个参数就是AttributeSet类型的。这里的attrs指的就是我们在XML布局文件中添加的属性。
  • int[] attrsArray:一个int类型的数组,它保存我们需要获取的属性ID,也就是我们在res/values/attrs.xml中所声明的属性。

在获取属性值时,我们一般使用了三个方法:

  • getColor(int index, int defValue):获取颜色值,如果取出来的值为NULL,就用Entry的默认值(默认值一定要传入)
  • getDimension(int index, float defValue):获取尺寸值,参数同上
  • getString(int index):获取字符串值

2.4 示例

例如,我们自定义一个ProgressBar控件,它包含了两个属性:progressColor和progressHeight。属性的定义和使用如下:

<resources>
    <declare-styleable name="ProgressBar">
        <attr name="progressColor" format="color"/>
        <attr name="progressHeight" format="dimension"/>
    </declare-styleable>
</resources>

<com.example.view.ProgressBar
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    custom:progressColor="#FF0000"
    custom:progressHeight="10dp"/>

ProgressBar的具体实现如下:

public class ProgressBar extends View {
    private int progressColor = Color.RED;
    private float progressHeight = 5;

    private Paint mPaint;

    public ProgressBar(Context context) {
        super(context);
        init(context, null);
    }

    public ProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        final float percentage = 0.5f;//计算出当前进度占总宽度的百分比
        final float progressWidth = getWidth() * percentage;
        mPaint.setColor(progressColor);
        mPaint.setStrokeWidth(progressHeight);
        canvas.drawLine(0, getHeight() / 2, progressWidth, getHeight() / 2, mPaint);
    }

    /**
     * 初始化
     */
    private void init(Context context, AttributeSet attrs) {
        if (attrs != null) {
            TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ProgressBar);
            progressColor = array.getColor(R.styleable.ProgressBar_progressColor, Color.RED);
            progressHeight = array.getDimension(R.styleable.ProgressBar_progressHeight, 5);
            array.recycle();
        }
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
    }
}

两个属性的绑定在构造函数中实现。可以看到,ProgressBar的实现与TextView的类似,只需要重写onDraw方法即可。其中,获取自定义属性值的代码,就在构造方法中使用了TypedArray类实现。

3. 总结

自定义属性作为自定义控件的一部分是非常重要的,可以通过自定义属性方便地在XML文件中设置控件属性,提高我们的开发效率。同时,我们也需要了解如何在代码中获取属性值,这样才能发挥自定义属性的效果。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Android自定义控件之自定义属性(二) - Python技术站

(0)
上一篇 2023年6月25日
下一篇 2023年6月25日

相关文章

  • Xp系统打不开QQ提示没有找到SSOCommon.DLL解决方案

    针对“Xp系统打不开QQ提示没有找到SSOCommon.DLL解决方案”的问题,我做以下回答。 问题描述 当使用XP操作系统登录QQ时,可能会出现“没有找到SSOCommon.DLL”的错误提示,导致QQ无法打开。 解决方案 出现这种问题的主要原因是SSOCommon.dll文件缺失或已损坏,因此需要重新下载安装SSOCommon.dll文件。 步骤1:下载…

    other 2023年6月26日
    00
  • 设置应用程序在Win11中崩溃怎么办?应用程序在Win11中崩溃解决方法

    针对应用程序在Win11中崩溃这个问题,可以根据以下几个步骤来尝试解决: 1. 更新系统和应用程序 首先,需要确保系统和应用程序都是最新的版本。可以通过“设置”应用进入“更新和安全”页面,点击“检查更新”来更新系统。同时,也需要打开应用商店或者前往应用程序官方网站,下载最新版本的应用程序。 2. 重新启动电脑 有时候,电脑长时间运行或者存在一些系统繁忙的情况…

    other 2023年6月25日
    00
  • iOS9开发者预览版固件下载地址汇总

    iOS9开发者预览版固件下载地址汇总 简介 本文旨在为广大iOS开发者提供一份完整的iOS9开发者预览版固件下载地址汇总,以方便开发者高效获取开发资料。 下载地址 iOS9开发者预览版的固件下载地址由苹果公司官方网站提供,下载前请确保自己已加入开发计划并获得了相应权限。以下是几条常用的下载地址: iPhone 6 Plus iPad Air 2 (6th G…

    other 2023年6月26日
    00
  • C语言详解select函数的使用

    C语言详解select函数的使用 什么是select函数? select函数是Linux系统中的多路复用函数,它通过检查一组文件描述符(socket、文件、管道等)的状态来实现同时监视多个文件描述符的读写状态,并在其中的一个文件描述符可读写时进行相应的处理。可以说,select函数是实现I/O多路复用的重要工具之一。 select函数的语法 int sele…

    other 2023年6月27日
    00
  • PHP+Apache环境中如何隐藏Apache版本

    在PHP+Apache环境中,隐藏Apache版本可以增加服务器的安全性,防止攻击者利用已知的漏洞进行攻击。下面是隐藏Apache版本的完整攻略: 修改Apache配置文件: 打开Apache的配置文件,通常位于/etc/apache2/apache2.conf或/etc/httpd/httpd.conf。 在文件中找到ServerTokens指令,该指令用…

    other 2023年8月3日
    00
  • Vue实现实时更新sessionStorage数据的示例代码

    以下是使用Vue实现实时更新sessionStorage数据的示例代码的详细攻略: 创建Vue应用: 首先,确保您已经安装了Vue.js。可以使用以下命令进行安装: npm install vue 创建一个Vue应用的入口文件,例如app.js。 在入口文件中导入Vue并创建一个Vue实例。 监听sessionStorage变化: 在Vue实例的create…

    other 2023年10月17日
    00
  • CentOS7下python3.7.0安装教程

    下面我给您讲一下在CentOS7下安装Python3.7.0的完整攻略。 步骤一:安装必要的软件包 在安装Python3.7.0之前,我们需要先安装一些必要的软件包,包括开发工具和相关的库文件。可以通过以下命令进行安装: sudo yum groupinstall -y "Development Tools" sudo yum insta…

    other 2023年6月26日
    00
  • Python实现从URL地址提取文件名的方法

    下面是 Python 实现从 URL 地址提取文件名的方法的完整攻略。 步骤 导入 urllib.parse 模块。 使用 urlparse 函数解析 URL 地址,获取其路径部分。 使用 os.path 模块的 basename 函数从路径中提取文件名。 下面是具体的代码实现: import urllib.parse import os url = &qu…

    other 2023年6月26日
    00
合作推广
合作推广
分享本页
返回顶部