当我回想起初次接触Android系统时,对这三个概念感到相当困惑,有时仅对它们的基本用法有所了解,总体来说,心中充满了疑惑,无法说得十分明确。
[id_641031459]
撰写之初并未预料内容会如此繁复,写作过程中,由于细节考量周全云开·全站体育app登录,力求内容详尽,以便于“零基础”读者也能理解,结果篇幅逐渐拉长,因此建议读者收藏起来,闲暇时细细品读,保持耐心直至文末。
Attr基本概念
"Attr一词代表的是属性,但需注意,这里的属性与XML控件中的属性概念不同,请勿混淆。所谓的属性,其实是指Attr这个词本身的含义。我们通过Attr文件来设定控件中所用属性。或许这会让大家感到困惑,下面我就举一个例子来具体说明。"
比如我们在控件中最多使用的 layout_width 属性

该属性于“Attr”模块中进行定义,那么我们该如何寻找这一属性呢?请参照图片进行查看。


View属性
观察这幅图像,我们能够注意到在Android的软件开发工具包中,已经为我们创建了一个属性文件。
此处是对我们在控件中使用的属性进行了规定。接下来,我们不妨前往Android SDK所提供的attr文件中一探究竟。




这里的属性是为view控件所设定的,注释中已经解释得非常明确,这些属性是为View及其派生类所准备的,换句话说,这些属性在view及其子类中均可被应用。浏览这些属性,你是否觉得它们很熟悉?这不就是我们编写布局时经常用到的那些属性吗?
TextView属性
让我们再仔细审视一下Android软件开发工具包中为TextView控件所设定的属性集合。

等等,在此处,我们使用的控件均配备了相应的属性声明。浏览至此,你是否已领悟“attr”的含义?实际上,“attr”指的是一个文件,其中详细列出了我们控件所涉及的所有属性。
具体的说一下attr的一些知识如何定义attr?
我们首先来看看Android的官方属性是如何进行定义了

观察发现,起初定义了一组属性,并为其命名称为 TextView,随后在其中详细描述了一系列属性。
我在这里总结了属性的定义格式:
1 "TextView">
2 "属性1" format = "这个属性的取值格式">
3 <enum name="取值1" value="程序中对应的值"/>
<enum name="取值1" value="程序中对应的值"/>
<enum name="取值1" value="程序中对应的值"/>
<enum name="取值1" value="程序中对应的值"/>
4 "取值1" value="程序中对应的值" />
"取值2" value="程序中对应的值" />
"取值3" value="程序中对应的值" />
通常情况下,我们自定义属性主要用于自定义View的开发。若在定义属性时省略了format,那么在布局文件中引用该属性时,将不会收到提示信息。然而,只要确保布局文件中填写的属性值与Java文件中的取值相匹配,就不会出现任何问题。尽管如此,仍建议为format指定一个明确的值,这样做可以使代码更加清晰,降低出错的可能性。此外,我们提前为该属性设定了若干个值,可以直接从这些预定义的值中进行选择。4号版本的不同之处在于,flag的运用方式在布局文件中表现为:直接列出取值1或取值2,这表明它可以接受多个不同的值。
例子:

此处正是我们经常采用的layout_width设定方法:我们能够将layout_width的数值设定为fill_parent、match_parent、wrap_content,亦或是自行输入具体尺寸。
至于textStyle,我们的可选值众多,这里就不再一一详述了。
好了,下面我们可以自己来定义属性了。

重点来介绍format里面的一些值
fraction:百分数
例子:
使用:
app:xshow = “70%”
reference : 指定某一资源ID
例子:
在配置文件中,需指定应用背景资源,具体方式为:通过属性app:backgroundresourece赋值为“@drawable/id”。
别的格式基本上就是见名知意,就不再介绍了。
属性的取值
在某些特定情境中,我们或许希望某个属性能够继承另一个属性的数值,这样的表述或许显得有些难以理解。下面,请允许我通过一个实例来为您展示。

这幅图展示了我自行设定的一项属性,在我设计的界面布局中包含了一个TextView组件。我想要实现的是,让这个TextView显示的内容与test_attr的值相同,该如何操作呢?

没错,就是通过使用`attr/属性名字`的格式来获取test_attr这个属性的值,假如test_attr是
在Android系统中,如何获取attr值呢?其引入方式为:使用“?android:attr/属性名字”或者直接省略“attr”。
以上的操作都有一个前提:
attr的值仅在theme中得以赋值时才具备有效性,否则若未在theme中设定,程序将可能报错。需注意,某些主题可能已为属性设定了默认值,此时引用attr值不会出错;然而,若没有默认值,且未在theme中正确定义,则会导致错误。换言之,必须在清单文件中的Application或Activity部分配置Theme,且确保Theme所指向的属性具有值,方能引用attr的值。单独在控件中通过android:Theme或app:theme添加样式是无效的。
obtainStyledAttributes详细说明
在开发自定义视图时,为了获取我们定义的属性值,通常的做法是:
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable属性组名,定义样式属性,默认样式资源;
a.getXX(R.styleable.XX_xxx);
a.recycle();
关于方法obainStyledAttributes()

这个方法实际上存在于Context中,其最终调用的实为getTheme()方法中的功能。因此,我们有时会发现context.obtainStyledAttributes与context.getTheme().obtainStyledAttributes在本质上并无二致。
下面来仔细说说这个方法:
我们可以看到
public final TypedArray obtainStyledAttributes(AttributeSet set, @StyleableRes int[] attrs) {
return获取主题对象,调用其获取样式属性的方法。set, attrs, 0,0);
}
最终是调用的是这个
public TypedArray obtainStyledAttributes(AttributeSet set,@StyleableRes int[] attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
returnmThemeImpl 获取样式属性对象,以供后续使用。this, set设置属性、默认样式属性定义、默认样式资源;
}
让我们来探讨一下这一技巧,简言之kaiyun全站网页版登录,它涉及生成一个TypedArray对象——一个用于存储属性数据的数组——其中包含的参数
集合:这是与XML标签相连接的属性存储集合,其中int类型属性是我们需要在XML文件中提取的数据。
defStyleAttr:它指的是当前主题下的一个特定属性,这个属性内含对专为TypedArray指定默认样式的资源引用。若设置为0,则表示不进行默认值的查找。
defStyleRes指的是特定的样式资源。它作为TypedArray的默认值样式资源标识符,仅在defStyleAttr为0或主题中无法找到相应属性时才会被采用。此外,defStyleRes也可以设置为0,以此避免去搜索默认值。
这么说起来可能有点迷糊,来一个例子保证你立马领悟!
首先我在attrs中定义一组属性

attr_defStyle 属性名称,正是我所设定的 defStyleAttr,它是在 obtainStyledAttributes 方法中作为参数被使用的。
然后自己定义style和Theme


我在上面的注释中已经写得很清楚了,就不多解释了。
然后再自定义View

通常情况下,第一个构造方式指的是在Java代码中通过使用`new`关键字创建控件,而第二个构造方式则是在解析XML文件生成视图时被调用的。
可以看到我在 第二个构造方法中是这样写的
在此上下文中,调用函数以应用属性,并指定默认样式引用,即R.attr.attr_defStyle;同时,对传入的参数进行限制,确保符合规定的样式定义。
在R.attr中,attr_defStyle代表的是定义的defStyle,我已在自定义的Theme中为其赋予了特定的值。这一做法进一步阐释了先前的观点,即attr_defStyle是当前主题的一部分,其中包含了对于style(即style_attr_defStyleAttr)的引用。
R.style.style_defStyleRes这一表述非常清晰,它指的是一种对style资源的引用方式。
再来看看布局页面

在布局文件中,我为其指定了text1属性以及样式设置,现在我们来观察程序执行后的效果。
看到这个运行结果就得出结论了,关于属性的取值是由顺序的
1.优先取在布局中给定的值
2.在布局中设置的style中的值
在获取defStyleAttr和defStyleRes的值时,需留意一点:若defStyleAttr中已有设定,便无需再从defStyleRes中取值,即便defStyleAttr中某些属性尚未被赋予具体值。(详情可参考上方的打印输出。)
4.Theme中设置的属性
务必确保在主题设置中正确配置defStyleAttr的数值,否则将无法产生预期效果。以先前示例为例,若未在主题中为R.attr.attr_defStyle指定具体值,而仅是在布局文件中进行赋值,那么这种做法将不会产生任何作用。
在进行了上述的说明之后,我们不妨进一步探究系统的工作原理kaiyun.ccm,以一个普通的button控件为例,来观察其具体操作方式。

我们观察到,在button的构造方法中,defStyleAttr所传递的是com.android.internal.R.attr.buttonStyle这一属性,而这一属性,我们可以在系统的attr文件中查找到。

这就是系统定义的默认属性buttonStyle
我们再来看看系统Theme是怎么给它附的值

这里给了一个指引,指向了一个style

因此,我们的按钮在各个主题中均设定了既定的外观。不妨观察一下,系统中的设定是否与我们自行设定的样式颇为相似呢?
现在清楚了吗?建议还是多看看源码。
小知识点
在此,"parent"这一概念可以视作"MyStyle"从"Widget.Button"那里继承了特性。这种继承通常源自于系统层面,然而,当一种样式继承自其自身的风格时,情况就有所不同了。
<style name = "MyStyle.H">
<item ----->item>
style>
是的这里使用. 表示H 继承自MyStyle
关于Attr的讲解已告一段落,原本计划在一篇文章中详述完毕,然而在撰写过程中篇幅逐渐膨胀,这主要是因为我考虑到许多基础性问题,为了确保大家都能理解,内容便随之增多。至于style和theme部分,预计篇幅同样庞大。在撰写过程中,我发现涉及的知识点十分广泛,几乎想要将所有内容都介绍给大家。

水平有限有什么问题可以指正批评


