网易首页 > 网易号 > 正文 申请入驻

Android 自定义View属性相关细节

0
分享至

1

概述

在自定义View中去定义属性、获取属性,相关大家肯定都不陌生,不过在整个过程中还是会涉及到一些可能被大家忽略的细节问题。

今天的文章主要讨论下面几个细节:

1、obtainStyledAttributes 四个参数的详细的作用。

2、自定义View中构造方法中调用初始化代码,两种写法的区别。

3、自定义View中获取自定义属性,两种写法的区别 。

是不是现在在想两种写法是什么玩意?恩,看完就知道了。

2

obtainStyledAttributes详解

(1)基本用法

ok,首先看一个非常常见的写法,假设我有一个自定义View叫做:AttrView,我们随便给它定义几个属性:

res/values/attrs.xml

对于在自定义View里面获取以上的属性,那么一般我们的代码是这样的:

相信大家都很熟悉了~~

obtainStyledAttributes这个方法实际上最终调用的是:

可以看到实际上有4个参数,那么对于后两个参数到底是干嘛的呢,怎么使用呢?

我们先看第4个参数,再看第3个参数。

(2)defStyleRes

接下来,我们先看最后一个参数,最后一个参数叫`defStyleRes `,其实是用于指定一个style,如下:

我们在styles.xml里面编写:

可以看到我们声明了一个style,然后我们修改我们刚才获取属性的代码,修改为:

ok,目前我们的布局文件是这样的(并未设置任何属性):

运行看下结果:


E/TAG﹕ test1 = false
E/TAG﹕ test2 = 3333
E/TAG﹕ test3 = 278//139dp

运行结果很明显的可以看出,如果我们不在布局文件中设置任何属性,那么会从在这个style中读取相关属性。

下面接续看第三个参数

(3)defStyleAttr

注释上是这么描述的:

An attribute in the current theme that contains a reference to a style resource

说明它是一个引用类型的属性,指向一个style,并且在当前的theme中进行设置,如下:

那么首先,我们先声明一个attr,当然还是写在attrs.xml里面:

添加了一个新的引用格式的属性`attrViewStyleRef `。

然后去styles.xml里面,找到我们所使用的theme,添加一条item:

然后修改我们关键的一行代码:

再次运行的结果为:


E/TAG﹕ test1 = true
E/TAG﹕ test2 = 10086
E/TAG﹕ test3 = 1776//888dp

那么对于第三个参数呢,实际上用的还是比较多的,比如看系统的Button,EditText,它们都会在构造里面指定第三个参数:

提供一些参数的样式,比如background,textAppearance,textColor等,所以当我们切换不同的主题时,你会发现控件的样式会发生一些变化,就是因为不同的主题,设置了一些不同的style。

那么推演到我们自定义的View,如果你的属性非常多,你也可以去提供默认的style,然后让用户去设置到theme里面即可。

那么这样的话,大家对于obtainStyledAttributes应该有了进一步的认识,不过,如果同时设置defStyleAttr与defStyleRes,那么哪个优先级更高呢?

defStyleRes的注释是这样介绍的:

A resource identifier of a style resource that supplies default values for the TypedArray, used only if defStyleAttr is 0 or can not be found in the theme.

那么可以看出,只有defStyleAttr设置为0或者在当前的theme中没有找到相关属性时,才会去defStyleRes中读取,那么很明显优先级是defStyleAttr更高,具体的实验大家自己测试。

ok,那么解决了今天的第一个问题,接下来下一个。

3

构造方法中调用初始化代码

大家可能会困惑,哪两种写法呢?

(1)第一种

(2)第二种

对于两种写法,大家都不陌生吧,肯定的,谁都见过,但是很少有人会去问:这两种有什么区别呢?

说实话,区别不大,但是在使用场景上还是需要注意的,下面简单说几个场景。

1. 如果需要设置obtainStyledAttributes的第三个参数,即`defStyleAttr`,一般会使用第一种方式,会在两个参数的构造中,去调用三个参数的构造,同时传入`defStyleAttr `。如果没有此需求,两种写法没有什么区别。

2. 继承系统已有的控件去自定义View,比如你继承Button,去做一些事情。

第一种方式会覆盖掉Button默认在theme里面设置的style,相对来说第二种方式更为合适(这条是一定要注意的,切记,切记)。

那么我们简单写个例子:

你在布局文件里面去声明,最后的效果是这样的:

看到这样的效果,你信它是个按钮吗?

当然了,如果你继承系统这个View,完全不在乎它原本的样子,那么就无所谓了。

这种情况呢,也是存在的,就是我要的是系统控件的特性,但是它的样子不需要,比如你可以看到这个代码,继承了ProgressBar,因为要自定义UI风格,完全不需要系统的默认的样子,于是使用了第一种方式。

https://github.com/hongyangAndroid/Android-ProgressBarWidthNumber

4

获取自定义属性两种写法的区别

看到这个标题,你是不是很郁闷,我擦,获取自定义属性,也有两种写法?

(1) 第一种方式

略(就是我们上面的写法)。

(2)第二种方式

等你细细的看完,你可能会认为,我擦,这种写法好傻逼,直接指定index不就行了,这个for循环根本没鸟用。其实并不是这样的,这种写法有它考虑到的地方,而且系统中很多类中获取属性的方式都是这样的方式(例如:TextView)。

不过,这种写法和第一种写法还是有一定的区别的:

第一种写法,不管你有没有在布局文件中使用该属性,都会去执行getXXX方法赋值,

第二种写法,只有在你布局文件中设置了该属性后,才会去调用getXXX方法赋值。

那么,有什么影响呢?

假设这么个场景:


private int attr_mode = 1;//默认为1
//然后你在写getXXX方法的时候,是这么写的:
attr_mode = array.getInt(i, 0);

可能你的自定义属性有个默认的值,然后你在写赋值的时候,一看是整形,就默默的第二个参数就给了个0,然而用户根本没有在布局文件里面设置这个属性,你却在运行时将其变为了0(而不是默认值),而第二种就不存在这个问题。当然这个场景可以由规范的书写代码的方式来避免,(把默认值提取出来,都设置对就好了)。

其实还有个场景,假设你是继承自某个View,父类的View已经对该成员变量进行赋值了,然后你这边需要根据用户的设置情况,去更新这个值,第一种写法,如果用户根本没有设置,你可能就将父类的赋值给覆盖了。

在日常编码中时候,这些细节经常被忽视,而且很难发现!

ok,文本都是一些自定义View时平时可能会忽略的东西,希望可以帮助到你。

你还遇到过哪些值得注意的地方?欢迎留言。

--- End ---

欢迎关注公众号。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
副董事长林斌被指违背承诺减持套现1.6亿 小米回应:是做公益

副董事长林斌被指违背承诺减持套现1.6亿 小米回应:是做公益

财联社
2024-06-20 13:45:08
全球首秀!华为Mate70已进入最后阶段:实力派,长这样!

全球首秀!华为Mate70已进入最后阶段:实力派,长这样!

最潮家居评
2024-06-20 16:07:54
引退理由揭密!さつき芽衣(沙月芽衣):因为那支作品让我流血了!

引退理由揭密!さつき芽衣(沙月芽衣):因为那支作品让我流血了!

日本这些事儿
2024-06-20 16:05:19
幽默段子:给表婶打电话,听她说话气喘吁吁的。我坏笑着说让她忙吧,但手机没挂。没想到,表婶也没挂……

幽默段子:给表婶打电话,听她说话气喘吁吁的。我坏笑着说让她忙吧,但手机没挂。没想到,表婶也没挂……

微法官
2024-05-15 00:03:23
德转官宣!前德甲冠军队两大王牌夏窗亮相中国足坛,新东家已敲定

德转官宣!前德甲冠军队两大王牌夏窗亮相中国足坛,新东家已敲定

罗掌柜体育
2024-06-20 20:24:31
啊啊啊!求你了叶璇,别再老黄瓜刷绿漆装嫩了!饶了我们的眼睛吧

啊啊啊!求你了叶璇,别再老黄瓜刷绿漆装嫩了!饶了我们的眼睛吧

一只爱8卦的小月巴子
2024-06-19 08:05:03
中国发出警告:90天内不支付358亿赔偿金,18艘军舰就别想要了

中国发出警告:90天内不支付358亿赔偿金,18艘军舰就别想要了

星辰故事屋
2024-06-09 17:09:59
惨不忍睹!广州火灾现场电动车爆燃,多辆轿车受影响。

惨不忍睹!广州火灾现场电动车爆燃,多辆轿车受影响。

小毅讲历史
2024-06-20 14:30:19
韩国丑系男爱豆因整容太成功而出圈!网友感叹前后简直大变活人!

韩国丑系男爱豆因整容太成功而出圈!网友感叹前后简直大变活人!

奋斗在韩国
2024-06-20 17:20:23
乔治:在这个阶段,我并不一定是追逐总冠军,下一个明星是班凯罗

乔治:在这个阶段,我并不一定是追逐总冠军,下一个明星是班凯罗

好火子
2024-06-21 04:22:27
4岁女孩被3只狗围住,狗主人叫嚣咬了就打疫苗,结果被暴打

4岁女孩被3只狗围住,狗主人叫嚣咬了就打疫苗,结果被暴打

飞花文史
2024-06-20 15:00:59
真·绝平!响哨前最后1秒,700万空霸拯救塞尔维亚,创欧洲杯2纪录

真·绝平!响哨前最后1秒,700万空霸拯救塞尔维亚,创欧洲杯2纪录

我爱英超
2024-06-20 23:20:18
揭底!余琦身世背景不容小觑,网友:怪不得连道歉都有底气

揭底!余琦身世背景不容小觑,网友:怪不得连道歉都有底气

记录生活日常阿蜴
2024-06-20 10:43:38
C罗儿子长大了!和继母拥抱庆生,母子关系真好,乔治娜身材极品

C罗儿子长大了!和继母拥抱庆生,母子关系真好,乔治娜身材极品

三十年莱斯特城球迷
2024-06-19 16:39:54
再见皇马,1500万+二转,转投意甲豪门,佛爷没挽留,保留回购

再见皇马,1500万+二转,转投意甲豪门,佛爷没挽留,保留回购

球文速递
2024-06-20 07:30:28
笑疯!林更新:不想和刘亦菲离婚,网友:麻溜点,霍建华等着呢!

笑疯!林更新:不想和刘亦菲离婚,网友:麻溜点,霍建华等着呢!

墙头草
2024-06-18 08:13:50
一个麻六记开业仪式,就能让人明白大S为什么输给马筱梅!

一个麻六记开业仪式,就能让人明白大S为什么输给马筱梅!

毒舌嬷嬷
2024-06-20 14:33:59
天哪!王思聪有私生女不算什么,这才是王家最大的瓜

天哪!王思聪有私生女不算什么,这才是王家最大的瓜

洛子帅品评
2024-06-19 10:54:32
王思聪女儿王闪闪变“国民公主”,一天涨粉5位数,评论区炸锅!

王思聪女儿王闪闪变“国民公主”,一天涨粉5位数,评论区炸锅!

娱圈小愚
2024-06-20 16:25:36
我女儿18岁,胸是D罩杯、嘴是豁嘴、塌鼻子、牙龈外翻,丑哭我了

我女儿18岁,胸是D罩杯、嘴是豁嘴、塌鼻子、牙龈外翻,丑哭我了

泡芙麻麻
2024-06-18 23:51:42
2024-06-21 06:52:49
君伟说
君伟说
分享职场故事
230文章数 48关注度
往期回顾 全部

科技要闻

小米SU7流量泼天,富贵却被蔚来接住了

头条要闻

欧洲杯:西班牙1-0意大利提前出线

头条要闻

欧洲杯:西班牙1-0意大利提前出线

体育要闻

千夫所指的关系户 成了拯救葡萄牙的英雄

娱乐要闻

叶舒华参加柯震东生日聚会,五毒俱全

财经要闻

楼市新“王炸”!释放何信号?

汽车要闻

售价11.79-14.39万元 新一代哈弗H6正式上市

态度原创

本地
健康
亲子
游戏
公开课

本地新闻

2024·合肥印象|用崭新视角对话城市发展

晚餐不吃or吃七分饱,哪种更减肥?

亲子要闻

18个月宝宝身高93cm、体重42斤,网友纷纷表示不敢相信!

魔兽世界怀旧服即将开服,正式服何时开放?官方早已透露玄机!

公开课

近视只是视力差?小心并发症

无障碍浏览 进入关怀版