Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 自定義控件之第三講:obtainStyledAttributes 系列函數詳解

Android 自定義控件之第三講:obtainStyledAttributes 系列函數詳解

編輯:關於Android編程

在項目中開發自定義控件時,或多或少都會用到 obtainStyledAttributes(AttributeSet, int[], int, int) 或者 obtainAttributes(AttributeSet, int[]) 函數,它們的主要作用是:根據傳入的參數,返回一個對應的 TypedArray ,如果小伙伴還沒有看過 LZ 的第二講,那麼請自行移步 Android 自定義控件之第二講:TypedArray 詳解,好了,就先扯到這裡,下面開始今天內容講解:

獲取 TypedArray 對象 的函數一共四個:

1.public TypedArray obtainStyledAttributes (int[] attrs)

2.public TypedArray obtainStyledAttributes (int resid, int[] attrs)

3.public TypedArray obtainAttributes (AttributeSet set, int[] attrs)

4.public TypedArray obtainStyledAttributes (AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)

講解之前,需要說明一點:函數 1、2、4 都是 Resources.Theme 的函數,而 3 是 Resources 的函數。

接下來,我們針對這四個函數一 一進行講解:

1. 解析前的准備

1. 在資源文件 values 下創建文件 attrs.xml,如下:




    
        
        
        
    

2. 在資源文件 layout 下創建文件 activity_main.xml,如下:



    


2. 解析

1. obtainStyledAttributes (int[] attrs)

Google Developer 是這麼解釋這個函數的:

這裡寫圖片描述

主要信息也就這麼一句:

Return a TypedArray holding the values defined by Theme which are listed in attrs

它的大意是:返回一個與 attrs 中列舉出的屬性相關的數組,數組裡面的值由 Theme 指定。從上面的概述中,我們可以知道:這個 Theme 就是關鍵。於是 LZ 各種試,皇天不負苦心人,謎底最終還是解開了:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPmF0dHJzILbU06a1xMr00NTWtbHY0Ou2qNLl1NogQXBwbGljYXRpb24g1tAgYW5kcm9pZDp0aGVtZSC21NOmtcQgc3R5bGUgz8KjrNKyvs3Kx8u1o7o8L3A+DQo8cD7O0sPH1NrOqiBBcHBsaWNhdGlvbiDJ6NbD1vfM4rXEzazKsdDo0qrU2rbU06a1xNb3zOLPws6qIGF0dHJzIMno1sPP4LnYtcTK9NDUo7o8L3A+DQo8cD48c3Ryb25nPjEuIMfltaXOxLz+PC9zdHJvbmc+PC9wPg0KPHByZSBjbGFzcz0="brush:java;">

2. styles 文件

3. 構造函數

TypedArray _TypedArray = mContext.getTheme().obtainStyledAttributes (R.styleable.MyFirstCustomerView);

應用程序運行效果如下:

這裡寫圖片描述

what?!

這些個奇怪字符都是從哪裡來的,其實 LZ 也不知道,但是打了個斷點看了下,發現從 mText = _TypedArray.getString(R.styleable.MyFirstCustomerView_text); 獲取數據的時候已經是這些奇怪字符了,出現問題了,當然有解決問題的辦法,我們只需要在構造函數裡面做如下操作:

if(!TextUtils.isEmpty(mText)){
            mText = "第一種";
}

這樣之後,就是我們想要的效果了:

這裡寫圖片描述

對!就是這麼個情況,搜了下貌似沒有人遇到上面的問題,關鍵這個函數本來就很少有人用,所以等後面吧,也許未來的某一天,LZ 靈機一動,就知道這個問題的答案了,哈哈~,開玩笑~

不知道小伙伴有沒有發現,我們在 Layout 布局文件中也為 attrs 對應的屬性賦值了,其實簡單的分析下就可以知道:無論我們有沒有在 Layout 布局文件中為 attrs 對應屬性賦值,這些值都不會起作用,因為這些值是從 Theme 中獲取的,不相信的小伙伴可以自己試下,答案肯定和 LZ 分析的一樣。

2. obtainStyledAttributes (int resid, int[] attrs)

Google Developer 是這麼解釋這個函數的:

這裡寫圖片描述

細心的朋友一定會發現,其實這個函數的解釋和上面的那個差不多。沒錯!格式幾乎一樣,因此我們只需要仿照上面的例子,找出這句話裡面的關鍵字即可:

Return a TypedArray holding the values defined by the style resource resid which are listed in attrs

這句話的大意是:返回一個與 attrs 中列舉出的屬性相關的數組,數組裡面的值由 樣式屬性resid 指定。其實這句話已經很明確了,因此我們就不做過多的贅述,直接上 Demo:

1. 清單文件


        
            
                

                
            
        
    

2. styles 文件


    

3. 構造函數

TypedArray _TypedArray = mContext.getTheme().obtainStyledAttributes (R.style.MyFirstCustomerViewStyle_1,R.styleable.MyFirstCustomerView); 

應用程序運行效果如下:

這裡寫圖片描述

對,就是這麼簡單!

同上個函數一樣,因為 attrs 的屬性都是 style 文件中獲取的,因此無論是否在 Layout 布局文件中為 attrs 添加屬性,這些值都不會起作用。

3. obtainAttributes (AttributeSet set, int[] attrs)

Google Developer 是這麼解釋這個函數的:

這裡寫圖片描述

相信在自定義控件的時候,應該有好多小伙伴和 LZ 一樣喜歡用這個函數吧。

同上面兩個函數一樣,也是一句話:

Retrieve a set of basic attribute values from an AttributeSet, not performing styling of them using a theme and/or style resources.

這句話的大意是:從 AttributeSet 中獲取 attrs 對應的屬性值,不為這些屬性值設置樣式。

考慮到很多小伙伴經常使用這個函數,因此,直接上 Demo:

1. XML 布局文件


    

2. 清單文件


        
            
                

                
            
        
    

3. 構造函數

TypedArray _TypedArray = mContext.getResources().obtainAttributes (attrs,R.styleable.MyFirstCustomerView)

不知道小伙伴還記不記得 LZ 在上面說過這個函數的特殊性—— Resources 裡面的函數。

應用程序運行效果如下:

這裡寫圖片描述

同上面的兩個函數不同,在這個函數裡面的有個特別的參數 AttributeSet,它對應著 attrs 裡面的屬性,AttributeSet 對象中的數據是從 XML 布局文件中讀取出來的,因此此時如果我們不在布局文件中為 attrs 相關屬性設置值,那麼就會報錯!報錯!!報錯!!!切記,小伙伴~

4. obtainStyledAttributes (AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)

Google Developer 是這麼解釋這個函數的:

這裡寫圖片描述

相信很多人看完這麼多的注釋之後都蒙圈了,LZ 也不例外,第一次看的時候,稀裡糊塗的就看完了,看完之後,發現什麼也沒懂~就是知道怎麼用,但是具體裡面的細節,一問三不知。終於今天靜下心好好研究了下,把之前所有的迷惑都解開了,接下來就讓我將這個函數講個一清二楚吧,哈哈~

上面的 Google 開發者文檔的大意是:

返回一個與 attrs 屬性相對應的數組。另外,如果在 AttributeSet 中為 attrs 指定了樣式屬性,那麼這個樣式屬性就會應用在這些屬性上。

attribute 最終由下面四個因素決定:

在 AttributeSet 中定義的屬性(Any attribute values in the given AttributeSet);

AttributeSet 指定的樣式資源文件(The style resource specified in the AttributeSet (named “style”));

由 defStyleAttr 和 defStyleRes 指定的樣式資源文件(The default style specified by defStyleAttr and defStyleRes);

主題中的默認值(The base values in this theme)。

上面四種元素的優先級是從上到下排序的,也就是說:如果在 AttributeSet 中定義了某個屬性的值,那麼無論後面的樣式屬性如何定義,它的值都不會改變。

接下來我們分別解釋下,函數中各參數的含義:

AttributeSet set :XML 中定義的屬性值,可能為 null;

int[] attrs :目標屬性值;

int defStyleAttr :在當前主題中有一個引用指向樣式文件,這個樣式文件將 TypedArray 設置默認值。如果此參數為 0 則表示不進行默認值設置。

int defStyleRes :默認的樣式資源文件,只有當 defStyleAttr 為 0 或者無法在對應的主題下找到資源文件時才起作用。如果此參數為 0 則表示不進行默認設置。

好了,接下來就開始這部分的講解吧:

1. attrs 文件




    
        
        
        
        
        
    

2. style 文件


    
    
    
    
    
    

3. xml 布局文件

4. 清單文件


        
            
                

                
            
        
    

5. 構造函數

TypedArray _TypedArray = mContext.getTheme().obtainStyledAttributes(attrs,  R.styleable.MyFirstCustomerView, R.attr.myCustomerStyle, R.style.MyFirstCustomerViewStyle_3);

應用程序運行效果如下:

這裡寫圖片描述

這是默認情況,在這種情況下,因為 AttributeSet 屬性不為 null,因此後面的兩個參數的作用是無法體現出來的。

於是乎,接下來,我們就讓 AttributeSet 為 null。看有什麼情況發生:

其他地方都不改變,只需將構造函數稍微做下更改:

1. 構造函數

TypedArray _TypedArray = mContext.getTheme().obtainStyledAttributes(null,  R.styleable.MyFirstCustomerView, R.attr.myCustomerStyle, R.style.MyFirstCustomerViewStyle_3);

應用程序運行效果如下:

這裡寫圖片描述

有沒有覺得很神奇,沒錯,此時應用的正是第三個參數對應的樣式文件。

它的調用邏輯是這樣的:

這裡寫圖片描述

那麼,如果第三個參數為 0 會有怎樣的結果呢:

其他地方都不改變,只需將構造函數稍微做下更改:

1. 構造函數

TypedArray _TypedArray = mContext.getTheme().obtainStyledAttributes(null,  R.styleable.MyFirstCustomerView, 0, R.style.MyFirstCustomerViewStyle_3);

應用程序運行效果如下:

這裡寫圖片描述

不知道小伙伴是否還記得 LZ 在講此函數四個決定因子時說過,它們的優先級是從高到底依次排列的:

AttributeSet > defStyleAttr > defStyleRes

這樣一說之後,我想小伙伴肯定都知道怎麼會出現上面三種情況了吧。好了,到這裡,這篇文章也就講完了,接下來,我們做個總結:

1. 獲取 TypedArray 對象 的函數一共四個:

1.obtainStyledAttributes (int[] attrs)

2.obtainStyledAttributes (int resid, int[] attrs)

3.obtainAttributes (AttributeSet set, int[] attrs)

4.obtainStyledAttributes (AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)

2. 第三個和第四個是最常用的。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved