@android, ?attr/ 和 ?android 的区别
前言:安卓开发中我们时常会需要引用一些特殊的资源,比如设置一些可点击组件的波纹效果时,我们会用到:android:foreground="?attr/selectableItemBackground",但是这些引用方式之间有哪些区别呢?
00 获取资源
首先来复习一下安卓中获取资源的几种方式。
@[<package_name>:]<resource_type>/<resource_name>
这种方式是最为常见的,直接获取对应的包下的资源,一般在相同的包下,可以省略包名,比如为 TextView 设置文字时,就可以通过这样的方式来获取我们应用内定义的 string 资源:
android:text="@string/hello"
另一种获取资源的方式是通过引用 style
属性。
android:textColor="?colorAccent"
通过这种方式,我们可以获取到当前应用主题下的 style
属性值,这些属性值一般可以在属性文件夹 values
下找到。这里由于当前使用的是 Theme.AppCompat
下的主题,这是 com.android.support:appcompat-v7
下的 Theme,所以 colorAccent
会指向该库下的 values
文件:
关于资源引用的方式,具体请参考官方文档:Accessing your app resources
01 @android: 引用安卓内建的系统资源
除了引用自己应用中的资源外,我们还可以通过指定引用时的包名为 android
来获取安卓平台下的一些系统资源,举个例子:
android:background=“@android:drawable/ic_menu_delete”
我们知道当新建一个项目的时候,必须在 gradle 中设置 compileSdkVersion
来指定编译我们应用的 SDK 版本,这也决定了我们能调用哪个 level 的 API,同时也表明了哪个 level 的系统资源可供我们使用,比如如果指定的 compileSdkVersion
是 27,那么我们调用的就是 Android 8.1 下的系统资源。
02 ?attr/: 引用应用内的属性资源
通过这种方式可以让我们间接地使用应用内的某些资源。我们知道当我们自定义View的时候,一般会需要自定义一些属性资源,通常我们会在 values/
文件夹下建一个 attrs
文件,在这里保存一些我们自己的 style 属性,其实这些属性就可以通过 ?attr/
这种方式来引用了。比如我在 styles
里定义了一个属性:
<attr name="colorReallyGreen" format="color"/>
定义完之后,我就可以直接在 layout
中通过引用的方式去使用这个属性了:
android:background="?attr/colorReallyGreen"
当然,要想让该属性起作用还需要在 Theme 下指定值:
在当前 Theme 下为自定义属性赋值另外,由于在 layout
中,可以自动识别出当前所需的是属性资源,所以可以省略 attr/
而直接使用 ?colorReallyGreen
就可以了。
03 ?android: 引用系统内建的属性资源
了解了前两种资源引用的方式后,?android
这种引用资源的方式也就不难理解了。与 ?attr/
类似,通过这种方式可以直接访问到安卓内建的属性资源,只不过是省略了 attr/
而已。比如给 TextView 引用一个系统内的 style buttonStyleSmall
:
<TextView
style="?android:buttonStyleSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="You Are Beautiful" />
然后 TextView 就变成了这样:
引用了安卓内建属性作为 style 的 TextView当然如果你尝试去掉 android
包名之后,发现该属性还是可以起作用,说明应用内也是可以引用这个资源的。那么这是不是意味着绝大部分属性资源都不需要加 android
包名呢?其实我觉得是这样的,因为加了包名之后其实限制反而会更多,比如有些内建属性资源是针对某个 API level 以上的 Android 平台才可以使用的,当然这也与你当前使用的 Theme 有关。
结语
合理利用安卓内建资源其实可以节约我们很多时间,每一个安卓开发都应该花点时间探索下。
参考:
[1]: https://stackoverflow.com/questions/36642430/whats-the-difference-between-androidattr-and-attr-in-an-android-layout "What‘s the difference between “?android:attr/” and “?attr/” in an android layout xml file?"
[2]: http://grishma102.blogspot.com/2015/02/difference-between-attr-and-androidattr.html "Difference between “?attr/” and “?android:attr/” in android"