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

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日

相关文章

  • win10预览版Build 10130快速版官方简体中文iso镜像下载地址

    Win10预览版Build 10130快速版官方简体中文ISO镜像下载攻略 Win10预览版Build 10130快速版是微软发布的操作系统预览版本,本攻略将详细介绍如何获取官方简体中文ISO镜像的下载地址。以下是完整的攻略过程: 步骤一:访问微软官方网站 首先,打开你的浏览器,访问微软官方网站 https://www.microsoft.com/zh-cn…

    other 2023年8月5日
    00
  • 定常系统(时不变系统)和时变系统&&动态系统和静态系统

    定常系统(时不变系统)和时变系统 定常系统(时不变系统) 定常系统,也称为时不变系统,是指系统的输出不随时间变化而变化,系统的输出只与输入有关,与时间无关。在数学上,定常系统可以表示为: y(t) = f(x(t)) 其中,y(t)表示系统的输出,x(t)表示系统的输入,f表示系统的传递函数。 定常系统的特点是稳定性好,易于分析和设计。例如,一个线性时不变系…

    other 2023年5月7日
    00
  • NAS208阵列柜磁盘文件系统是什么格式?

    NAS208阵列柜是一种网络存储设备,用户可以选择不同的磁盘来存储数据。其磁盘文件系统格式会影响用户的数据备份和恢复操作。下面我将详细讲解NAS208阵列柜磁盘文件系统的格式以及如何进行选择。 了解各种文件系统格式 在NAS208阵列柜中的磁盘分为两种类型:固态硬盘和机械硬盘。对于机械硬盘,用户可以选择的文件系统格式有:EXT4、EXT3、FAT32、NTF…

    other 2023年6月27日
    00
  • 详解Android布局加载流程源码

    详解Android布局加载流程源码的攻略如下: 1. 确定需求 在详细讲解Android布局加载流程源码之前,需要先了解本次攻略的目的和需求。本次攻略的目的是通过对Android布局加载流程源码的分析,深入了解Android布局加载的过程和原理,以便进一步优化相关的开发工作。 2. 学习布局加载流程 2.1 布局加载的基本流程 Android布局加载的基本流…

    other 2023年6月25日
    00
  • 关于Dev-C++的安装以及基本使用方法图文入门

    这里是关于Dev-C++的安装以及基本使用方法的完整攻略。 Dev-C++ 安装 Dev-C++是一个免费的集成开发环境(IDE),用于编写和调试C/C++代码。在开始使用之前,需要先进行安装。具体步骤如下: 在 Dev-C++官网 下载最新版的 Dev-C++ 安装包。 双击安装包文件 devcpp-x.x.x.xxx_setup.exe 打开安装向导。 …

    other 2023年6月26日
    00
  • CentOS 添加环境变量的三种方法(图文教程)

    下面是“CentOS 添加环境变量的三种方法(图文教程)”的完整攻略: 1. 编辑 profile 文件 步骤如下: 打开一个终端,输入以下命令进入 root 用户: su – 输入 root 用户的密码,按下回车键进行确认。 进入 /etc 目录,找到 profile 文件: cd /etc 使用文本编辑器(如 vim)打开 profile 文件: vim…

    other 2023年6月27日
    00
  • 详解Linux系统无法上网解决方案

    针对“详解Linux系统无法上网解决方案”的完整攻略,我将分为以下几步来详细讲解: 1. 检查网络连接状态 首先,我们需要检查网络连接状态,确定是否已经连接上了网络。可以在终端中运行以下命令: ping www.baidu.com 如果能够正常 ping 通百度的服务器,就说明网络连接正常。如果无法 ping 通,说明存在网络连接问题,此时需要进一步排查。 …

    other 2023年6月26日
    00
  • docker-如何重命名docker镜像名称?

    在Docker中,我们可以使用docker tag命令来重命名镜像名称。以下是一个完整的攻略,介绍如何在Docker中重命名镜像名称。 步骤1:查看当前镜像列表 在重命名镜像名称之前,我们需要查看当前的镜像列表,以确定要重命名的镜像名称。可以使用docker images命令来查看当前的镜像列表。以下是一个示例: docker images 在上面的示例中,…

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