转载Android 自定义View属性相关细节

转载 2016年05月31日 10:08:59

看了大神的文章觉着很有用所以就copy 过来了留存 ,原文请关注“鸿洋”微信查看

1 概述

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

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

obtainStyledAttributes 四个参数的详细的作用
自定义View中构造方法中调用初始化代码,两种写法的区别
自定义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,完全不在乎它原本的样子,那么就无所谓了。这种情况呢,也是存在的,就是我要的是系统控件的特性,但是它的样子不需要,比如:https://github.com/hongyangAndroid/Android-ProgressBarWidthNumber,你可以看到这个代码,继承了ProgressBar,因为要自定义UI风格,完全不需要系统的默认的样子,于是使用了第一种方式。

4

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

(1) 第一种方式

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

(2)第二种方式

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

注:如果switch报错,可以改为if-else

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

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

那么,有什么影响呢?

假设这么个场景:

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

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

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

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

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

Android自定义View(二、深入解析自定义属性)

转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51454685 本文出自:【openXu的博客】 [TOC] 在上一篇博...
  • u010163442
  • u010163442
  • 2016年05月21日 03:53
  • 17577

Android 自定义View 之 自定义View属性

我们可以自定义View,当然也可以自定义View的属性。下面就从多个方面来介绍自定义View属性的使用。在使用自定义属性之前,我们需要定义属性。一般我们会按下面的步骤来进行:...
  • mybeta
  • mybeta
  • 2014年10月10日 23:50
  • 2300

Android自定义View获取自定义属性

首先扯点别的:今晚回家做了一个鱼香肉丝,刚学的,出锅以后,才想起没有放豆瓣酱,也是没谁了。不过吃起来还行,吃了三块煎饼。今天记录一下自定义View的构造函数的使用,以及如何获取自定义属性。先看一下自定...
  • leilifengxingmw
  • leilifengxingmw
  • 2017年04月18日 23:25
  • 1588

Android 深入理解Android中的自定义属性

1、引言 对于自定义属性,大家肯定都不陌生,遵循以下几步,就可以实现: 自定义一个CustomView(extends View )类 编写values/attrs.xml,在其中编写styl...
  • lmj623565791
  • lmj623565791
  • 2015年04月13日 10:42
  • 118603

自定义View——坑、技巧、调优

相信有创建过“自定义View”经验的众多的开发者朋友当中有相当一部分人猿友是直接copy网上的一些代码拿来用,结果往往不尽如人意, 碰到bug或者是需求发生变化时往往手忙脚乱,android自定义Vi...
  • sinat_15877283
  • sinat_15877283
  • 2016年04月04日 14:28
  • 1523

属性动画ValueAnimator在自定义View中的使用 属性动画核心类

http://mafei.site/2016/07/17/android-valueanimator/ 功能强大的属性动画(property animation) 最近...
  • lhq186
  • lhq186
  • 2016年07月25日 22:57
  • 1656

Android 自定义View属性相关细节

从鸿洋的公众号上看到的,在博客上没找到,自己也一直疑惑所以记了下来。 自定义View中构造方法中调用初始化代码,两种写法的区别 (1)第一种 (2)第二种 对于两种写法,...
  • qiaoyl113
  • qiaoyl113
  • 2017年01月05日 15:45
  • 93

Android 自定义View属性相关细节总结

1概述    在自定义View中去定义属性、获取属性,相关大家肯定都不陌生,不过在整个过程中还是会涉及到一些可能被大家忽略的细节问题。 今天的文章主要讨论下面几个细节: obta...
  • lvwenbo0107
  • lvwenbo0107
  • 2016年05月24日 09:38
  • 324

Android 自定义View属性相关细节

1概述    在自定义View中去定义属性、获取属性,相关大家肯定都不陌生,不过在整个过程中还是会涉及到一些可能被大家忽略的细节问题。 今天的文章主要讨论下面几个细节: ...
  • snow_Lu
  • snow_Lu
  • 2016年05月27日 16:52
  • 444

自定义View—自定义属性及引用

学习导航….后续添加,自定义view不是一章能说清的。本章讲解: 自定义视图,我们需要做哪些准备!对于一些中级的开发者来说就要接触到自定义视图,由于Android自带的视图无法满足自己需求,又或者美观...
  • bobo8945510
  • bobo8945510
  • 2016年11月17日 12:02
  • 2228
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:转载Android 自定义View属性相关细节
举报原因:
原因补充:

(最多只允许输入30个字)