Android 自定义View时四个构造函数使用详解

server/2025/1/30 23:49:07/

该文章我们以自定义View继承TextView为例来讲解

创建自定义View命名MyTextView,并使其继承TextView

1、自定义View时第一个构造函数

// 第一个构造函数主要是在Java代码中声明一个MyTextView时所用
// 类似这种(MyTextView myTextView=new MyTextView(this);)
// 不过如果只用第一个构造函数,声明的View并没有任何的参数,基本是个空的View对象

2、自定义View时第二个构造函数

//在XML布局文件中引用时,系统初始化该View时,调用的是第二个构造函数
//参数attrs是我们在xml中配置的参数

前两个构造函数介绍完了,我们说下后两个构造函数

       系统默认只会调用前两个构造函数,至于后两个构造函数的调用,通常是我们自己在构造函数中主动调用的,TextView源码亦是如此:

      View类的后两个构造函数都是与主题相关的,也就是说,在你自定义View时,如果不需要你的View随着主题变化而变化,有前两个构造函数就OK了,但是如果你想你的View随着主题变化而变化,就需要利用后两个构造函数了。

  比如我们定义主题时,用两种方式给自定义View设置主题颜色,如下设置:

xml布局展示:

    在主题设置中颜色有两个赋值,为什么最终显示出来的颜色是绿色,而非紫色呢?????

    这就涉及到第三个构造函数了,例如源码中TextView,第三个构造函数的调用

3、自定义View时第三个构造函数

 不会自动调用,一般是在第二个构造函数里主动调用


3.1、第三个构造函数中的参数:defStyleAttr 是属性资源, 既然是属性资源,我们首先需要自定义属性

3.2、在主题中对这个自定义属性赋值。(红色)

3.3、构造函数中使用这个自定义属性

4、自定义View时第四个构造函数

   不会自动调用,一般是在第三个构造函数里主动调用

   第四个构造函数中,defStyleRes这个参数不再是Attr了,而是真正的style。

 4.1、定义一个真正的style(橙色)

4.2、在主题未声明属性值时,我们调用第四个构造函数,第四个参数赋值这个橙色style,以这种方式定义出的View,其主题就是这个定义的defStyleRes(想要最终结果显示橙色的前提是:只有在第三个参数defStyleAttr为0,或者主题中没有找到这个defStyleAttr属性的赋值时,才会启用)

由此也可见3种方式设置 textColor的优先级:

 defStyleAttr(红色) > defStyleRes(橙色) > theme 中直接定义(绿色)

//注解的意思是告诉Lint工具不需要对这个类进行 AppCompat 兼容性的检查
@SuppressLint("AppCompatCustomView")
public class MyTextView extends TextView {private final String TAG= MyTextView.class.getSimpleName();public MyTextView(Context context) {super(context);Log.d(TAG, "MyTextView: first ");}public MyTextView(Context context, @Nullable AttributeSet attrs) {//super指父类的//super(context, attrs);//this指当前对象,在这里是调用当前对象的第三个构造函数//this(context, attrs, R.attr.textViewColorStyle);this(context, attrs,0);Log.d(TAG, "MyTextView: second ");}public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {// super(context, attrs, defStyleAttr);//调用当前对象的第四个构造函数this(context, attrs,defStyleAttr, R.style.OrangeTextStyle);Log.d(TAG, "MyTextView: three ");}public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);Log.d(TAG, "MyTextView: four ");}}


http://www.ppmy.cn/server/163013.html

相关文章

MyBatis-Plus之常用注解

一、TableName 经过一系列的测试,在使用MyBatis-Plus实现基本的CRUD时,我们并没有指定要操作的表,只是在 Mapper接口继承BaseMapper时,设置了泛型User,而操作的表为user表 由此得出结论, MyBatis-Plus在确…

win11系统,Java web程序连不上数据的的解决办法

买了台新笔记本电脑,把代码和数据考了过来,想着能愉快的写代码了,程序起来发现连不上数据库。 所有的配置翻了一遍,也没发现问题,遂怀疑是系统的问题,原电脑是win10,现电脑是win11,所以晚上冲浪…

人工智能学习框架:深入解析与实战指南

📝个人主页🌹:一ge科研小菜鸡-CSDN博客 🌹🌹期待您的关注 🌹🌹 引言 随着人工智能(AI)技术的飞速发展,深度学习、强化学习和自然语言处理等领域的应用愈加广…

DeepSeek-R1:强化学习驱动的推理模型

1月20日晚,DeepSeek正式发布了全新的推理模型DeepSeek-R1,引起了人工智能领域的广泛关注。该模型在数学、代码生成等高复杂度任务上表现出色,性能对标OpenAI的o1正式版。同时,DeepSeek宣布将DeepSeek-R1以及相关技术报告全面开源。…

C++标准线程库实现优雅退出的方式

目录 1.通过设置共享退出标记 2.使用std::jthread创建线程 3.定义消息类型的方式 4.注意事项 1.通过设置共享退出标记 定义一个退出变量bool stop false; 表示线程是否应该停止。在主线程中设置标记stoptrue,然后join一直等待,然后线程循环检测到stop是否为tru…

【10.2】队列-设计循环队列

一、题目 设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。 循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普…

2025/1/21 学习Vue的第四天

睡觉。 --------------------------------------------------------------------------------------------------------------------------------- 11.Object.defineProperty 1.在我们之前学习JS的时候&#xff0c;普通得定义一个对象与属性。 <!DOCTYPE html> <h…

obsidian插件——Metadata Hider

原本是要找导出图片时显示属性的插件&#xff0c;奈何还没找到&#xff0c;反而找到了可以隐藏属性的插件。唉&#xff0c;人生不如意&#xff0c;十之八九。 说一下功能&#xff1a; 这个插件可以把obsidian的文档属性放在右侧显示&#xff0c;或者决定只显示具体几项属性&a…