天天看點

@android, ?attr/ 和 ?android 的差別

前言:安卓開發中我們時常會需要引用一些特殊的資源,比如設定一些可點選元件的波紋效果時,我們會用到:android:foreground="?attr/selectableItemBackground",但是這些引用方式之間有哪些差別呢?

1,擷取資源

首先來複習一下安卓中擷取資源的幾種方式。

@[<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

檔案:

@android, ?attr/ 和 ?android 的差別

關于資源引用的方式,具體請參考官方文檔:Accessing your app resources

2,@android: 引用安卓内建的系統資源

除了引用自己應用中的資源外,我們還可以通過指定引用時的包名為

android

來擷取安卓平台下的一些系統資源,舉個例子:

android:background=“@android:drawable/ic_menu_delete”
           

我們知道當建立一個項目的時候,必須在 gradle 中設定

compileSdkVersion

來指定編譯我們應用的 SDK 版本,這也決定了我們能調用哪個 level 的 API,同時也表明了哪個 level 的系統資源可供我們使用,比如如果指定的

compileSdkVersion

是 27,那麼我們調用的就是 Android 8.1 下的系統資源。

@android, ?attr/ 和 ?android 的差別

3,?attr/: 引用應用内的屬性資源

通過這種方式可以讓我們間接地使用應用内的某些資源。我們知道當我們自定義View的時候,一般會需要自定義一些屬性資源,通常我們會在

values/

檔案夾下建一個

attrs

檔案,在這裡儲存一些我們自己的 style 屬性,其實這些屬性就可以通過

?attr/

這種方式來引用了。比如我在

styles

裡定義了一個屬性:

<attr name="colorReallyGreen" format="color"/>
           

 定義完之後,我就可以直接在

layout

中通過引用的方式去使用這個屬性了:

android:background="?attr/colorReallyGreen"
           

當然,要想讓該屬性起作用還需要在 Theme 下指定值:

@android, ?attr/ 和 ?android 的差別

                                                   在目前 Theme 下為自定義屬性指派

另外,由于在

layout

中,可以自動識别出目前所需的是屬性資源,是以可以省略

attr/

而直接使用

?colorReallyGreen

就可以了。 

4,?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, ?attr/ 和 ?android 的差別

                        引用了安卓内建屬性作為 style 的 TextView

當然如果你嘗試去掉

android

包名之後,發現該屬性還是可以起作用,說明應用内也是可以引用這個資源的。那麼這是不是意味着絕大部分屬性資源都不需要加

android

包名呢?其實我覺得是這樣的,因為加了包名之後其實限制反而會更多,比如有些内建屬性資源是針對某個 API level 以上的 Android 平台才可以使用的,當然這也與你目前使用的 Theme 有關。