android 自定義View與Attr風格Style風格樣式

一.自定義View的主題和風格樣式

前言:

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>

這種事最全局的,提升了重用性,固然也有他的缺點,這點不可避免,那麼在開發中,咱們如何選擇呢?


  1. style.xml-1 中樣式變化最爲頻繁的View風格,這樣作能夠避免layout文件中過多的代碼累計,就像css樣式同樣

  2. style.xml-2適用於全局較爲統一的View風格,也就是說是一些View的共性的統一,通常來講如ToggleButton,CheckBox,Button等View的狀態切換樣式在同一項目中老是保持着一直的變化效果。也就是說,當咱們使用自定義放入ToggleButton切換狀態以後,下次再次使用ToggleButton風格應該和上次風格保持一致纔對。

  3. 衝突問題,若是在style.xml-2下使用style.xml-1的內容將如何顯示,這個問題一句話能夠描述:」全局性越低,控制權限越高「,也就是說,style.xml-1控制權限高於style.xml-2,所以若是同時影響某一控件的view風格的樣式被設置,那麼也就是直接使用 style="@style/xxxx"的權限高於主題權限。


二.自定義Attr風格樣式以及讀取

獲取自定義屬性一般是在自定義View內部獲取,但在某種方式下,不管自定義View的屬性仍是主題中樣式的屬性,都可在外部style中獲取。


因爲非自定義View的外部獲取方式比較複雜,這裏暫時略過,後續補充。

1.自定義attr
<?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>
2.設置attr,注意,該Attr必須在是Activity主題中而不是普通的Style中
<resources>
    <!-- Activity themes -->
    <style name="Theme.Base" parent="android:Theme.Holo.Light" >
    <item name="theme_name" >@string/theme_name_1</item>    
    </style>
</resources>
3.獲取,經過xml
 <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" />
4.獲取,經過代碼
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);
}
5.固然,有時候咱們的屬性多是個集合

  這時候不能用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;
    }
相關文章
相關標籤/搜索