在写布局文件的时候,我们经常用到@符号去引用资源,比如:
@color/white
@string/title_text
@drawable/button_selector
@mipmap/icon_launch
@layout/header_layout
@id/recyclerview
@style/appTheme
但有时还会见到?
,这是什么意思呢?
原来?
一般是用来引用一个attr属性的,例如,我给一个TextView设置如下的background
android:background="?attr/colorPrimary" // (1)
在styles.xml中定义如下的Theme
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/blue</item> <!-- (2) -->
<item name="android:windowFullscreen">true</item>
</style>
然后在AndroidMenifest.xml中,把上面TextView所在的Activity的Theme设置成它
<activity
android:name=".MainActivity"
android:screenOrientation="portrait"
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustPan"/>
(1)处用?号引用了colorPrimary这个属性,它的值在(2)处定义。
这就是?
大概的使用方法:
在Theme里面定义它,然后在用到的地方引用
下面有几点需要说明:
- 1.?attr/和?android:attr/的区别
如果我们在(1)处跳转进入,会跳到哪里呢?
看下图:
我们可以看到,是appcompat-v7包里定义的
但有时候,我们还会见到带有android命名空间的属性引用,这个和上面的写法有什么区别呢?我们试一下,把上面的(1)处修改为
android:background="?android:attr/colorPrimary" // (3)
我们同样的用F4
来跳转一下
这时我们看到,引用的是android sdk的attrs文件android-23\data\res\values\attrs.xml
中的定义
由此可见加上android命名空间就是引用的android sdk里面的,而不加的话就是引用的v7包里的
- 2.能否不用系统的或者v7包里的,我们自己起一个名字来引用呢?
答案是:可以
这时候需要做的就是在我们自己的attrs.xml文件中自定义一个属性,比如我定义了一个myColor
<declare-styleable name="colortest">
<attr name="myColor" format="color|reference"></attr>
</declare-styleable>
定义好了之后,怎么引用呢?显然不能用android命名空间了,我们试一下直接引用
android:background="?attr/myColor"
然后同样的,在Theme中定义它
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/blue</item>
<item name="myColor">@color/red</item>
<item name="android:windowFullscreen">true</item>
</style>
这样运行一下会发现,TextView的颜色变成了我们定义的红色
可见所引用的属性名字是可以自定义的
- 3.因此结合以上两点,我们可以总结一下了。
其实v7包虽然是android官方开发,但通常是作为我们本地引用的一个jar包,或者是用gradle的依赖引用过来的,不同于android sdk中的代码,它可以看做是本地的代码。所以其中的属性应用方式android:background="?attr/colorPrimary"
才和我们自己定义的属性引用方式相同android:background="?attr/myColor"
只有android sdk里面的属性才用?android:attr去引用