編輯:關於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 的函數。
接下來,我們針對這四個函數一 一進行講解:
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 分析的一樣。
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 添加屬性,這些值都不會起作用。
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 相關屬性設置值,那麼就會報錯!報錯!!報錯!!!切記,小伙伴~
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)MainActivity.javaimport android.app.Activity;import android.con
引言Android 中的Drawable是一個抽象的概念,換言之所有能被畫出來的都可以定義成Drawable(A Drawable is a general abstra
產品要做簽到功能,簽到功能要基於一個日歷來進行,所以就根據 要求自定義了一個日歷自定義控件相信做android都知道:(1)首先創建一個類,繼承一個容器類或者是一個控件&
本文實例講述了Android編程實現的重力感應效果。分享給大家供大家參考,具體如下:android中的很多游戲的游戲都使用了重力感應的技術,就研究了一下重力感應以屏幕的左