前言:安卓開發(fā)中我們時常會需要引用一些特殊的資源榄棵,比如設(shè)置一些可點擊組件的波紋效果時凝颇,我們會用到:android:foreground="?attr/selectableItemBackground",但是這些引用方式之間有哪些區(qū)別呢秉继?
獲取資源
首先來復(fù)習(xí)一下安卓中獲取資源的幾種方式祈噪。
@[<package_name>:]<resource_type>/<resource_name>
這種方式是最為常見的泽铛,直接獲取對應(yīng)的包下的資源尚辑,一般在相同的包下,可以省略包名盔腔,比如為 TextView 設(shè)置文字時杠茬,就可以通過這樣的方式來獲取我們應(yīng)用內(nèi)定義的 string 資源:
android:text="@string/hello"
另一種獲取資源的方式是通過引用 style
屬性。
android:textColor="?colorAccent"
通過這種方式弛随,我們可以獲取到當(dāng)前應(yīng)用主題下的 style
屬性值瓢喉,這些屬性值一般可以在屬性文件夾 values
下找到。這里由于當(dāng)前使用的是 Theme.AppCompat
下的主題舀透,這是 com.android.support:appcompat-v7
下的 Theme栓票,所以 colorAccent
會指向該庫下的 values
文件:
關(guān)于資源引用的方式,具體請參考官方文檔:Accessing your app resources
01 @android: 引用安卓內(nèi)建的系統(tǒng)資源
除了引用自己應(yīng)用中的資源外愕够,我們還可以通過指定引用時的包名為 android
來獲取安卓平臺下的一些系統(tǒng)資源走贪,舉個例子:
android:background=“@android:drawable/ic_menu_delete”
我們知道當(dāng)新建一個項目的時候,必須在 gradle 中設(shè)置 compileSdkVersion
來指定編譯我們應(yīng)用的 SDK 版本惑芭,這也決定了我們能調(diào)用哪個 level 的 API坠狡,同時也表明了哪個 level 的系統(tǒng)資源可供我們使用,比如如果指定的 compileSdkVersion
是 27遂跟,那么我們調(diào)用的就是 Android 8.1 下的系統(tǒng)資源逃沿。
02 ?attr/: 引用應(yīng)用內(nèi)的屬性資源
通過這種方式可以讓我們間接地使用應(yīng)用內(nèi)的某些資源婴渡。我們知道當(dāng)我們自定義View的時候,一般會需要自定義一些屬性資源凯亮,通常我們會在 values/
文件夾下建一個 attrs
文件边臼,在這里保存一些我們自己的 style 屬性,其實這些屬性就可以通過 ?attr/
這種方式來引用了假消。比如我在 styles
里定義了一個屬性:
<attr name="colorReallyGreen" format="color"/>
定義完之后硼瓣,我就可以直接在 layout
中通過引用的方式去使用這個屬性了:
android:background="?attr/colorReallyGreen"
當(dāng)然,要想讓該屬性起作用還需要在 Theme 下指定值:
另外置谦,由于在 layout
中堂鲤,可以自動識別出當(dāng)前所需的是屬性資源,所以可以省略 attr/
而直接使用 ?colorReallyGreen
就可以了媒峡。
03 ?android: 引用系統(tǒng)內(nèi)建的屬性資源
了解了前兩種資源引用的方式后瘟栖,?android
這種引用資源的方式也就不難理解了。與 ?attr/
類似谅阿,通過這種方式可以直接訪問到安卓內(nèi)建的屬性資源半哟,只不過是省略了 attr/
而已。比如給 TextView 引用一個系統(tǒng)內(nèi)的 style buttonStyleSmall
:
<TextView
style="?android:buttonStyleSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="You Are Beautiful" />
然后 TextView 就變成了這樣:
當(dāng)然如果你嘗試去掉 android
包名之后签餐,發(fā)現(xiàn)該屬性還是可以起作用寓涨,說明應(yīng)用內(nèi)也是可以引用這個資源的。那么這是不是意味著絕大部分屬性資源都不需要加 android
包名呢氯檐?其實我覺得是這樣的戒良,因為加了包名之后其實限制反而會更多,比如有些內(nèi)建屬性資源是針對某個 API level 以上的 Android 平臺才可以使用的冠摄,當(dāng)然這也與你當(dāng)前使用的 Theme 有關(guān)糯崎。
結(jié)語
總結(jié)下,獲取資源有兩種方式河泳,一種是通過直接引用(使用 @
)沃呢,一種是通過 style 屬性(使用 ?
,除了自定義屬性外拆挥,引用的資源類型和當(dāng)前使用的主題有關(guān))薄霜。另外系統(tǒng)中內(nèi)置了不少資源,學(xué)會合理利用它們可以幫助我們節(jié)約不少時間纸兔,建議大家花點精力自己探索下惰瓜。
參考: