Android學習系列(39)--Android主題和樣式之系統篇(上)

謙虛的天下發表於2014-05-17

【基於最新的Android4.4的原始碼分析】

每家公司或者每個移動團隊無不想開發出一套自己的UI框架,融入自己的設計和特性,這必然會去修改android的ui。
所以,學習和理解android的UI設計是最基礎和非常有必要的。
android ui設計最重要的就是主題和樣式。

1、位置
在Android的frameworks/base/core/res/res/values目錄下有一下幾個檔案:

themes.xml
themes_device_defaults.xml
styles.xml
styles_device_defaults.xml

分別定義了各種系統Theme,Style。

2、主題Theme
主要關注themes.xml,themes_device_defaults.xml兩個檔案。
themes.xml定義了android低版本的theme和Holo theme,themes_device_defaults.xml定義了DeviceDefault主題(繼承自Holo主題),實際上就是在Holo主題上定製主題(For廠商)。
系統如何去選擇預設的主題呢?

    /**frameworks/base/core/java/android/content/res/Resources.java*/
    /** @hide */
    public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {
        return selectSystemTheme(curTheme, targetSdkVersion,
                com.android.internal.R.style.Theme,
                com.android.internal.R.style.Theme_Holo,
                com.android.internal.R.style.Theme_DeviceDefault);
    }    
    
    /** @hide */
    public static int selectSystemTheme(int curTheme, int targetSdkVersion,
            int orig, int holo, int deviceDefault) {
        if (curTheme != 0) { 
            return curTheme;
        }    
        if (targetSdkVersion < Build.VERSION_CODES.HONEYCOMB) {
            // < 11
            return orig;
        }    
        if (targetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
             // < 14
             return holo;
        }    
        return deviceDefault;
    }

當<11時,使用以前低版本主題;當>=11&&<14,使用Holo主題;>14的時候,使用DeviceDefault主題。
方便理解,下面把目前所有的版本號列出來,也順便溫習一下android的歷史:

    public static class VERSION_CODES {
        /** 
         * Magic version number for a current development build, which has
         * not yet turned into an official release.
         */
        public static final int CUR_DEVELOPMENT = 10000;
    
        /** 
         * October 2008: The original, first, version of Android.  Yay!
         */
        public static final int BASE = 1;
    
        /** 
         * February 2009: First Android update, officially called 1.1.
         */
        public static final int BASE_1_1 = 2;
    
        /** 
         * May 2009: Android 1.5.
         */
        public static final int CUPCAKE = 3;

        /** 
         * September 2009: Android 1.6.
         */
        public static final int DONUT = 4;

        /**
         * November 2009: Android 2.0
         */
        public static final int ECLAIR = 5;

        /**
         * December 2009: Android 2.0.1
         */
        public static final int ECLAIR_0_1 = 6;

        /**
         * January 2010: Android 2.1
         */
        public static final int ECLAIR_MR1 = 7;

        /**
         * June 2010: Android 2.2
         */
        public static final int FROYO = 8;

        /**
         * November 2010: Android 2.3
         */
        public static final int GINGERBREAD = 9;

        /**
         * February 2011: Android 2.3.3.
         */
        public static final int GINGERBREAD_MR1 = 10;

        /**
         * February 2011: Android 3.0.
         */
        public static final int HONEYCOMB = 11;

        /**
         * May 2011: Android 3.1.
         */
        public static final int HONEYCOMB_MR1 = 12;

        /**
         * June 2011: Android 3.2.
         */
        public static final int HONEYCOMB_MR2 = 13;        

        /**
         * October 2011: Android 4.0.
         */
        public static final int ICE_CREAM_SANDWICH = 14;
        /**
         * December 2011: Android 4.0.3.
         */
        public static final int ICE_CREAM_SANDWICH_MR1 = 15;

        /**
         * June 2012: Android 4.1.
         */
        public static final int JELLY_BEAN = 16;

        /**
         * Android 4.2: Moar jelly beans!
         */
        public static final int JELLY_BEAN_MR1 = 17;

        /**
         * Android 4.3: Jelly Bean MR2, the revenge of the beans.
         */
        public static final int JELLY_BEAN_MR2 = 18;

        /**
         * Android 4.4: KitKat, another tasty treat.
         */
        public static final int KITKAT = 19;
    }  

3、系統主題Theme列表
系統預設大的主題是三種:Theme,Theme.Holo,Theme.DeviceDefault, 但是實際上在此基礎系統還定義了大量的派生主題,最典型的是對應的Light主題。
除此之外,還有很多,在此一一列出,打字太痛苦了,我貼出截圖:

瞭解android系統定義的主題之後,我們就可以根據實際情況在自己的應用中使用這些主題,但是如果想修改主題的某些內容,需要進一步深入。

4、詳解每個主題中定義item分類
一個完整的主題應該定義哪些內容呢,以Theme為例,如下:
1)顏色

        <item name="colorForeground">@android:color/bright_foreground_dark</item>
        <item name="colorForegroundInverse">@android:color/bright_foreground_dark_inverse</item>
        <item name="colorBackground">@android:color/background_dark</item>
        <item name="colorBackgroundCacheHint">?android:attr/colorBackground</item>

        <item name="colorPressedHighlight">@color/legacy_pressed_highlight</item>
        <item name="colorLongPressedHighlight">@color/legacy_long_pressed_highlight</item>
        <item name="colorFocusedHighlight">@color/legacy_selected_highlight</item>
        <item name="colorMultiSelectHighlight">@color/legacy_selected_highlight</item>
        <item name="colorActivatedHighlight">@color/legacy_selected_highlight</item>

2)字型

        <!-- Text styles -->
        <item name="textAppearance">@android:style/TextAppearance</item>
        <item name="textAppearanceInverse">@android:style/TextAppearance.Inverse</item>

        <item name="textColorPrimary">@android:color/primary_text_dark</item>
        <item name="textColorSecondary">@android:color/secondary_text_dark</item>
        <item name="textColorTertiary">@android:color/tertiary_text_dark</item>
        <item name="textColorPrimaryInverse">@android:color/primary_text_light</item>
        <item name="textColorSecondaryInverse">@android:color/secondary_text_light</item>
        <item name="textColorTertiaryInverse">@android:color/tertiary_text_light</item>
        <item name="textColorPrimaryDisableOnly">@android:color/primary_text_dark_disable_only</item>
        <item name="textColorPrimaryInverseDisableOnly">@android:color/primary_text_light_disable_only</item>
        <item name="textColorPrimaryNoDisable">@android:color/primary_text_dark_nodisable</item>
        <item name="textColorSecondaryNoDisable">@android:color/secondary_text_dark_nodisable</item>
        <item name="textColorPrimaryInverseNoDisable">@android:color/primary_text_light_nodisable</item>
        <item name="textColorSecondaryInverseNoDisable">@android:color/secondary_text_light_nodisable</item>
        <item name="textColorHint">@android:color/hint_foreground_dark</item>
        <item name="textColorHintInverse">@android:color/hint_foreground_light</item>
        <item name="textColorSearchUrl">@android:color/search_url_text</item>
        <item name="textColorHighlight">@android:color/highlighted_text_dark</item>
        <item name="textColorHighlightInverse">@android:color/highlighted_text_light</item>
        <item name="textColorLink">@android:color/link_text_dark</item>
        <item name="textColorLinkInverse">@android:color/link_text_light</item>
        <item name="textColorAlertDialogListItem">@android:color/primary_text_light_disable_only</item>

        <item name="textAppearanceLarge">@android:style/TextAppearance.Large</item>
        <item name="textAppearanceMedium">@android:style/TextAppearance.Medium</item>
        <item name="textAppearanceSmall">@android:style/TextAppearance.Small</item>
        <item name="textAppearanceLargeInverse">@android:style/TextAppearance.Large.Inverse</item>
        <item name="textAppearanceMediumInverse">@android:style/TextAppearance.Medium.Inverse</item>
        <item name="textAppearanceSmallInverse">@android:style/TextAppearance.Small.Inverse</item>
        <item name="textAppearanceSearchResultTitle">@android:style/TextAppearance.SearchResult.Title</item>
        <item name="textAppearanceSearchResultSubtitle">@android:style/TextAppearance.SearchResult.Subtitle</item>

        <item name="textAppearanceEasyCorrectSuggestion">@android:style/TextAppearance.EasyCorrectSuggestion</item>
        <item name="textAppearanceMisspelledSuggestion">@android:style/TextAppearance.MisspelledSuggestion</item>
        <item name="textAppearanceAutoCorrectionSuggestion">@android:style/TextAppearance.AutoCorrectionSuggestion</item>

        <item name="textAppearanceButton">@android:style/TextAppearance.Widget.Button</item>
        
        <item name="editTextColor">@android:color/primary_text_light</item>
        <item name="editTextBackground">@android:drawable/edit_text</item>
        
        <item name="candidatesTextStyleSpans">@android:string/candidates_style</item>
        
        <item name="textCheckMark">@android:drawable/indicator_check_mark_dark</item>
        <item name="textCheckMarkInverse">@android:drawable/indicator_check_mark_light</item>

        <item name="textAppearanceLargePopupMenu">@android:style/TextAppearance.Widget.PopupMenu.Large</item>
        <item name="textAppearanceSmallPopupMenu">@android:style/TextAppearance.Widget.PopupMenu.Small</item>

3)按鈕

        <!-- Button styles -->
        <item name="buttonStyle">@android:style/Widget.Button</item>

        <item name="buttonStyleSmall">@android:style/Widget.Button.Small</item>
        <item name="buttonStyleInset">@android:style/Widget.Button.Inset</item>

        <item name="buttonStyleToggle">@android:style/Widget.Button.Toggle</item>

        <item name="selectableItemBackground">@android:drawable/item_background</item>
        <item name="borderlessButtonStyle">?android:attr/buttonStyle</item>
        <item name="homeAsUpIndicator">@android:drawable/ic_ab_back_holo_dark</item>

4)List

        <!-- List attributes -->
        <item name="listPreferredItemHeight">64dip</item>
        <item name="listPreferredItemHeightSmall">?android:attr/listPreferredItemHeight</item>
        <item name="listPreferredItemHeightLarge">?android:attr/listPreferredItemHeight</item>
        <item name="dropdownListPreferredItemHeight">?android:attr/listPreferredItemHeight</item>
        <item name="textAppearanceListItem">?android:attr/textAppearanceLarge</item>
        <item name="textAppearanceListItemSmall">?android:attr/textAppearanceLarge</item>
        <item name="listPreferredItemPaddingLeft">6dip</item>
        <item name="listPreferredItemPaddingRight">6dip</item>
        <item name="listPreferredItemPaddingStart">6dip</item>
        <item name="listPreferredItemPaddingEnd">6dip</item>

5)Window

        <!-- Window attributes -->
        <item name="windowBackground">@android:drawable/screen_background_selector_dark</item>
        <item name="windowFrame">@null</item>
        <item name="windowNoTitle">false</item>
        <item name="windowFullscreen">false</item>
        <item name="windowOverscan">false</item>
        <item name="windowIsFloating">false</item>
        <item name="windowContentOverlay">@null</item>
        <item name="windowShowWallpaper">false</item>
        <item name="windowTitleStyle">@android:style/WindowTitle</item>
        <item name="windowTitleSize">25dip</item>
        <item name="windowTitleBackgroundStyle">@android:style/WindowTitleBackground</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Activity</item>
        <item name="android:windowSoftInputMode">stateUnspecified|adjustUnspecified</item>
        <item name="windowActionBar">false</item>
        <item name="windowActionModeOverlay">false</item>
        <item name="windowCloseOnTouchOutside">false</item>
        <item name="windowTranslucentStatus">false</item>
        <item name="windowTranslucentNavigation">false</item>

6)Dialog

        <!-- Dialog attributes -->
        <item name="dialogTheme">@android:style/Theme.Dialog</item>
        <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons</item>
        <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title</item>
        <item name="dialogTitleDecorLayout">@layout/dialog_title</item>

7)AlertDialog

        <!-- AlertDialog attributes -->
        <item name="alertDialogTheme">@android:style/Theme.Dialog.Alert</item>
        <item name="alertDialogStyle">@android:style/AlertDialog</item>
        <item name="alertDialogCenterButtons">true</item>
        <item name="alertDialogIcon">@android:drawable/ic_dialog_alert</item>

8)Panel

        <!-- Panel attributes -->
        <item name="panelBackground">@android:drawable/menu_background</item>
        <item name="panelFullBackground">@android:drawable/menu_background_fill_parent_width</item>
        <!-- These three attributes do not seems to be used by the framework. Declared public though -->
        <item name="panelColorBackground">#000</item>
        <item name="panelColorForeground">?android:attr/textColorPrimary</item>
        <item name="panelTextAppearance">?android:attr/textAppearance</item>

        <item name="panelMenuIsCompact">false</item>
        <item name="panelMenuListWidth">296dip</item>

9)滾動條(Scrollbar)

        <!-- Scrollbar attributes -->
        <item name="scrollbarFadeDuration">250</item>
        <item name="scrollbarDefaultDelayBeforeFade">300</item> 
        <item name="scrollbarSize">10dip</item>
        <item name="scrollbarThumbHorizontal">@android:drawable/scrollbar_handle_horizontal</item>
        <item name="scrollbarThumbVertical">@android:drawable/scrollbar_handle_vertical</item>
        <item name="scrollbarTrackHorizontal">@null</item>
        <item name="scrollbarTrackVertical">@null</item>

10)文字選中(Text selection)

        <!-- Text selection handle attributes -->
        <item name="textSelectHandleLeft">@android:drawable/text_select_handle_left</item>
        <item name="textSelectHandleRight">@android:drawable/text_select_handle_right</item>
        <item name="textSelectHandle">@android:drawable/text_select_handle_middle</item>
        <item name="textSelectHandleWindowStyle">@android:style/Widget.TextSelectHandle</item>
        <item name="textEditPasteWindowLayout">@android:layout/text_edit_paste_window</item>
        <item name="textEditNoPasteWindowLayout">@android:layout/text_edit_no_paste_window</item>
        <item name="textEditSidePasteWindowLayout">@android:layout/text_edit_side_paste_window</item>
        <item name="textEditSideNoPasteWindowLayout">@android:layout/text_edit_side_no_paste_window</item>
        <item name="textSuggestionsWindowStyle">@android:style/Widget.TextSuggestionsPopupWindow</item>
        <item name="textEditSuggestionItemLayout">@android:layout/text_edit_suggestion_item</item>
        <item name="textCursorDrawable">@null</item>

有點長,下篇繼續列舉,並深入分析具體style.

相關文章