梳理控件view自定义属性知识

        前言:   这几天在学习android的时候涉及到自定义属性这块内容。书本上讲的内容比较浅,查阅了好多网上博客资料和实际动手实践,总算对这一块大概搞明白了。之前也学习过这块内容,但是仅限于看书,过一段实际又忘了,因为工作性质不经常写代码,所以一直都这块不懂。每次遇到这里都要翻书本临时补一下,过几天又忘了。所以很有必要系统性总结一下,这样以后自己估计再也不会忘了。

1、涉及知识点介绍: 

 2、疑问

        我罗列了一下我在整理这块知识点的时候,遇到的疑惑点,我们带着问题来学习,然后解决问题。

  1. attr和declare-styleable中定义的attr之间有什么区别?
  2. attr和declare-styleable如何使用?
  3. 有了直接定义attr属性,为什么android又搞出一个declare-styleable?
  4. 能否在样式style和主题theme中使用非declare-styleable标签中定义的属性?
  5. declare-styleable中定义的attr可否在xml的自定义view标签中直接使用,而不是使用style的间接方式?同时使用时其优先级是怎样?
  6. 如何在主题theme中使用declare-styleable标签中定义的属性?
  7. context.obtainStyledAttributes()函数中每个参数的意义和函数内部逻辑?

3、解惑

        首先解释下下面一直用到的两个定义:直接定义的attr属性(没有声明在declare-style的属性)和declare-style内部声明的属性

3.1 attr和declare-styleable中定义的attr之间有什么区别?

        可以/res/values/目录下的attrs.xml中或其他命名的xml中定义属性(一般按照规范是在attrs.xml中定义)

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="attrTvColor2" format="color"/>
    <declare-styleable name="AttrTextView">
        <attr name="attrTvName" format="string"/>
        <attr name="attrTvSize" format="integer"/>
    </declare-styleable>
</resources>

定义好属性后,同步sync一下工程。在build/intermediates/runtime_symbol_list/debug/R.txt中(最新的android studio中基于性能优化已不会动态生成R.java文件了,而是输出原本R.java中的内容到R.txt中)

int attr attrTvColor2 0x7f030037
int attr attrTvName 0x7f030038
int attr attrTvSize 0x7f030039

int[] styleable AttrTextView { 0x7f030038, 0x7f030039 }
int styleable AttrTextView_attrTvName 0
int styleable AttrTextView_attrTvSize 1

相关资料上显示了R.java 的内容可以参考

 在这里我们可以看到通过修改attrs.xml,R文件的改变是多了两个类,分别是attr类和styleable类,这里我们要注意的是区分出来这两个类,他们是不同的,后面获得TypedArray的时候他们的区别就会很明显。在我理解,attr就是属性呗,就像定义一个变量似的定义一个属性。styleable就是样式,就是属性的集合,在R文件里体现的很明显,button1就是样式,它包含两个属性的地址,就是0x7f010001和0x7f010002。还有一个值得注意的地方时button1_textSize1这个属性,它的作用就是下标。后面我们在TypedArray里取值的时候会用到。

3.2 attr和declare-styleable如何使用?

属性使用通用步骤:

  1. 在属性文件xx.xml文件中定义属性attr的name,format;
  2. 自定义view,在其构造函数中获取属性值
  3. 在xml的自定义view标签中使用属性并赋值

情况1:xml文件中直接定义的attr属性,其使用步骤如下

  •  xml文件中定义自定义属性:

  •  自定义view,并在其构造函数中获取自定义属性的取值(属性值是在使用的时候赋值的)。有两种方式获取自定义属性值:

a、 遍历自定义view的属性列表set,获取每个属性的资源id,即resId, 然后通过resId判断是否是想要的属性,是的话再获取属性值:

b、通过属性的命名空间和属性名,直接获取属性值。属性值统一为String类型,自己转换成真实属性值类型即可: 

  • 在xml的自定义view标签中直接使用属性并赋值 

情况2: xml文件中使用declare-styleable标签内部定义的属性,其使用步骤为:

  • xml中通过declare-styleable标签定义属性 --> 然后使用style标签定义一个样式 -->最后在xml的view标签使用样式就可以应用自定义属性了
  •  自定义view,并在其构造函数中获取自定义属性的取值(属性值是在使用的时候赋值的)。

这里涉及到TypedArray和obtainStyledAttributes()函数的用法,放到后面再讲。

 3.3、有了直接定义的attr属性,为什么android又搞出一个declare-styleable?

        这个问题我想了很久,后来慢慢想通。如果只有直接定义的attr属性,想象一种情况:我们的自定义view在多个地方被使用,并且这个view使用到的属性和属性值是一样的,我们将不得不在每次使用view标签时把这些属性都手动地重复添加一遍。基于这个现状,我们知道样式style是一系列属性的集合,那我们可以利用style的方式解决上面的问题:在style中添加我们的自定义属性,然后在view中就只需要添加一行即可,即“style=@style/xxxx”。

        在android中,要想使用style标签,则在style内部使用的属性必须来自于declare-styleable声明可样式化属性。自定义view的构造函数中配套获取属性值的方法是obtainStyledAttributes(),该函数有一个参数是R.styleable.xxx(其中xxx就是declare-styleable标签的name)。

3.4、 能否在样式style和主题theme中使用非declare-styleable标签中定义的属性?

        首先给出答案是不能,原因是:

        1、由于直接定义的attr属性在R.java中只生成了R.attr.xxx的值,并没有R.styleable-xxx的值。

        2、假如在style标签中使用非declare-styleable标签中定义的属性,那么在自定义view的构造函数中去获取设置的style属性值时调用的是obtainStyledAttributes(),这个函数是通过R.styleable.xxx来获取属性值的。 这里就和第一点冲突了,也就是说我们无法获取到该属性值。

3.5、 declare-styleable中定义的attr可否在xml的自定义view标签中直接使用,而不是使用style的间接方式?同时使用时其优先级是怎样?

        答案是可以的。同时使用的话,直接使用的方式优先级比通过style的间接方式优先级更高。原因在介绍obtainStyledAttributes()函数用法是讲解。

 3.6、如何在主题theme中使用declare-styleable标签中定义的属性?

        话不多说,直接上图

方式1:theme中使用引用类型的属性

 方式2:theme中直接使用declare-styleable定义的属性

 其他省略部分和方式1是一致的,就不贴图了。

 方式3、theme中直接使用直接定义的属性

        这里我尝试了一下,发现在自定义view中没办法获取该属性值。 因为属性不是在自定义view标签中直接使用的,所以AttributeSet attrs中没有这个属性,再者这个属性没有声明在declare-styleable中,也无法通过 typedArray.getString(R.styleable.AttrTextView_xxx);来获取。但是我看theme中的确是有其他item的属性是直接定义的,所以这里应该是超出了我目前的知识范围,这个以后遇到了再补充吧!!!

3.8、context.obtainStyledAttributes()函数中每个参数的意义和函数内部逻辑?

这里主要是参考另外两篇博客就可以了
Android中View自定义XML属性详解以及R.attr与R.styleable的区别View 绘制体系知识梳理(8) - obtainStyledAttributes 详解

不过我还是自己简单用总结,下面有鱼刺图展示:

补充:只有在前一个鱼刺中找不到属性的时候,才会在下一个鱼刺上尝试进行匹配 。

下面再补充下各个参数的含义:

AttributeSet set:

        xml文件中自定义view标签上使用的所有属性,包括直接使用的属性和通过style间接使用的属性;

@StyleableRes int[] attrs:

        通过declare-styleable定义的属性集合。这些属性都是obtainStyledAttributes()函数获取的目标属性。并且数组中属性id必须是升序的。该参数使用@StyleableRes注解修饰,代表我们可以直接使用R.styleable.xxx (它实际上也是一个数组)。

int defStyleAttr:

        其值的是当前主题中使用到的一个属性, 这个属性的值是一个引用类型,引用的是一个样式,并且样式中提供了需要获取的属性。defStyleAttr=0代表不需要从主题中获取属性。

        额外说下defStyleAttr的参数命名方式,def--default,该参数是主题的一个属性,所以其本质是一个属性attr, 属性的值类型是style,所以这个参数最后被命名为defStyleAttr。

int defStyleRes:

          该值是一个样式资源,该资源提供了TypedArray数组的默认值。仅仅在defStyleAttr=0,或defStyleAttr在主题中找不到时,才会尝试从这个style中获取想要的属性值。defStyleRes=0代表不需要为TypedArray数组设置默认值。

下面补充下获取属性的相关api

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF(Windows Presentation Foundation)是微软开发的一种基于.NET Framework的图形显示子系统,用于开发用户界面和图形相关的应用程序。在WPF中,我们可以使用自定义控件自定义属性来满足特定的需求和设计要求。 自定义控件是通过继承现有的WPF控件类来实现的。通过继承,我们可以重写控件的行为和外观,添加自定义的功能和特性。例如,我们可以创建一个名为CustomButton的自定义按钮控件,添加额外的事件、样式和布局等。自定义控件使得我们能够灵活地调整和扩展现有的控件库,使应用程序的用户界面更加独特和富有创意。 自定义属性是在自定义控件中添加的自定义属性。这些属性可以满足特定的设计需求,可以通过属性设置来改变控件的行为和外观。例如,在CustomButton控件中,我们可以添加一个名为CustomColor的自定义属性,用于设置按钮的背景颜色。通过在XAML中设置CustomButton的CustomColor属性值,我们可以实现按钮背景颜色的动态修改。 对于自定义属性的实现,我们需要先在控件类中定义一个依赖属性,并为这个属性添加属性变更回调函数。这样,当属性的值发生变化时,回调函数会被触发,我们可以在回调函数中执行相应的逻辑操作。在XAML中,我们可以通过控件标签属性来设置自定义属性的值,也可以使用数据绑定的方式将属性与其他对象关联起来。 总之,WPF的自定义控件自定义属性给我们在开发中提供了更多灵活性和定制性。我们可以根据具体的需求创建独特的控件,通过自定义属性来调整控件的行为和外观。这些功能使得我们能够更好地满足用户的需求,创建更加丰富和个性化的应用程序界面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值