前言:安卓開發中我們時常會需要引用一些特殊的資源,比如設置一些可點擊組件的波紋效果時,我們會用到:android:foreground="?attr/selectableItemBackground",但是這些引用方式之間有哪些區別呢?
獲取資源
首先來復習一下安卓中獲取資源的幾種方式。
@[<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 下指定值:
另外,由于在 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 就變成了這樣:
當然如果你嘗試去掉 android
包名之后,發現該屬性還是可以起作用,說明應用內也是可以引用這個資源的。那么這是不是意味著絕大部分屬性資源都不需要加 android
包名呢?其實我覺得是這樣的,因為加了包名之后其實限制反而會更多,比如有些內建屬性資源是針對某個 API level 以上的 Android 平臺才可以使用的,當然這也與你當前使用的 Theme 有關。
結語
總結下,獲取資源有兩種方式,一種是通過直接引用(使用 @
),一種是通過 style 屬性(使用 ?
,除了自定義屬性外,引用的資源類型和當前使用的主題有關)。另外系統中內置了不少資源,學會合理利用它們可以幫助我們節約不少時間,建議大家花點精力自己探索下。
參考: