android開發中,不可避免的要設定某一類按鈕的按壓,點擊,聚焦等狀態,一般對於這一類問題而言,最原始的方式就是在佈局文件中親自設定,然而對於一個比較大型的項目而言,這種方式形成的可維護性不是很好,所以要儘可能作到代碼重用。對於一個控件而言,如ToggleButton,RadioButton,CheckBox,滾動條顏色,Button,當點擊時狀態切換先後樣式是不同的。css
android項目中一般有3個設置樣式的資源文件夾
java
valuesandroid
values-11api
values-14app
這三個對應不一樣平臺的sdk版本的樣式,對於android開發中兼容問題而言,要作到「讓最新的api運行在最新的android sdk中」,這是很是好的一種行爲。佈局
values文件主要用來設置主題樣式,權限依據平臺細分,也就是說android4.x會最早找values-14再去找values-11最後找values,android2.x最早找values-11最後找valuesspa
以上是values的設置問題,一般來講,style.xml通常被使用來設置 window和activity主題與樣式,但實際上,style.xml也能夠用來設定控件的全局樣式。code
下面有句名言:orm
儘可能讓主題樣式和頁面風格保持統一,花花綠綠是最醜的風格。xml
style.xml-1
<style name="text_red_20_blod"> <item name="android:textStyle">bold</item> <item name="android:textSize">20.0sp</item> <item name="android:textColor">@color/red_text_color</item> </style>
這種的侷限性和親自到佈局文件設置的同樣,只不過少了許多代碼,提升了重用性,能夠說只作到了部分全局化。
style.xml-2
<style name="AppTheme" parent="android:Theme.Holo.Light"> <item name="android:textStyle">bold</item> <item name="android:textSize">20.0sp</item> <item name="android:textColor">@color/red_text_color</item> </style>
這種事最全局的,提升了重用性,固然也有他的缺點,這點不可避免,那麼在開發中,咱們如何選擇呢?
style.xml-1 中樣式變化最爲頻繁的View風格,這樣作能夠避免layout文件中過多的代碼累計,就像css樣式同樣
style.xml-2適用於全局較爲統一的View風格,也就是說是一些View的共性的統一,通常來講如ToggleButton,CheckBox,Button等View的狀態切換樣式在同一項目中老是保持着一直的變化效果。也就是說,當咱們使用自定義放入ToggleButton切換狀態以後,下次再次使用ToggleButton風格應該和上次風格保持一致纔對。
衝突問題,若是在style.xml-2下使用style.xml-1的內容將如何顯示,這個問題一句話能夠描述:」全局性越低,控制權限越高「,也就是說,style.xml-1控制權限高於style.xml-2,所以若是同時影響某一控件的view風格的樣式被設置,那麼也就是直接使用 style="@style/xxxx"的權限高於主題權限。
獲取自定義屬性一般是在自定義View內部獲取,但在某種方式下,不管自定義View的屬性仍是主題中樣式的屬性,都可在外部style中獲取。
因爲非自定義View的外部獲取方式比較複雜,這裏暫時略過,後續補充。
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android"> <attr name="theme_name" format="string|reference"/> </resources>
<resources> <!-- Activity themes --> <style name="Theme.Base" parent="android:Theme.Holo.Light" > <item name="theme_name" >@string/theme_name_1</item> </style> </resources>
<TextView android:id="@+id/show_tv" android:layout_width="match_parent" android:layout_height="200dip" android:text="?attr/theme_name" android:background="@android:color/darker_gray" />
TypedValue outValue = new TypedValue(); getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground,outValue, true); textView.setBackgroundResource(outValue.resourceId);
注意,若是我直接設置數據,則resourceId爲0
<resources> <!-- Activity themes --> <style name="Theme.Base" parent="android:Theme.Holo.Light" > <item name="theme_name" >個人主題</item> </style> </resources>
這時候咱們的數據可使用TypeValue.string讀取
TypedValue outValue = new TypedValue(); getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground,outValue, true); if(outValue.data==TypeValue.TYPE_STRING) { textView.setBackgroundResource(outValue.string); }
這時候不能用TypedValue獲取,TypeValued只能判斷類型,所以咱們選擇以下方式
5.1在xml中,咱們使用 style="?attr/MyStyle"或者style="?android:attr/ActionBarStyle"方式獲取集合Style的
5.2在代碼中獲取,舉個栗子,以下:
public int getTabContainerHeight() { TypedArray a = mContext.obtainStyledAttributes(null, android.support.v7.appcompat.R.styleable.ActionBar, android.support.v7.appcompat.R.attr.actionBarStyle, 0); int height = a.getLayoutDimension(android.support.v7.appcompat.R.styleable.ActionBar_height, 0); Resources r = mContext.getResources(); if(!hasEmbeddedTabs()) height = Math.min(height, r.getDimensionPixelSize(android.support.v7.appcompat.R.dimen.abc_action_bar_stacked_max_height)); a.recycle(); return height; }
對於View內部獲取方式以下
private static Context themifyContext(Context context, AttributeSet attrs, int defStyleAttr) { TypedArray a = context.obtainStyledAttributes(attrs, android.support.v7.appcompat.R.styleable.Toolbar, android.support.v7.appcompat.R.attr.ActionBarStyle, 0); int themeId = a.getResourceId(android.support.v7.appcompat.R.styleable.Toolbar_theme, 0); if(themeId != 0) context = new ContextThemeWrapper(context, themeId); a.recycle(); return context; }