自定義ActionBar風格和樣式

一、實現效果圖

豎屏效果圖:最左邊是Logo圖標,右邊是工具欄按鈕,點擊Menu鍵顯示其餘的按鈕鍵,下方是Tab標籤選項。





橫屏效果圖:豎屏中的Tab選項標籤變成了中間的下拉導航按鈕







二、項目結構圖



三、編碼準備工作

先來學習一下自定義樣式的基礎知識,以便大家能看懂關於後面的代碼。

1、設置操作欄的樣式

       如果你對應用程序中的可視構件進行了定製化的設計,那麼你可能也會要對操作欄做一些重新設計,以便跟應用程序的設計匹配。要這樣做的話,需要使用Android的樣式與主題框架中的一些特殊的樣式屬性來重新設置操作欄的樣式。

       注意:改變外觀的背景圖片依賴與當前按鈕的狀態(選擇、按下、解除選擇),因此你使用的可描畫的資源必須是一個可描畫的狀態列表。

       警告:對於你提供的所有可描畫的背景,要確保使用NinePatch類型可描畫資源,以便允許圖片的拉伸。NinePatch類型的圖片應該比40像素高30像素寬的圖片要小。


2、普通的外觀

android:windowActionBarOverlay

      這個屬性聲明瞭操作欄是否應該覆蓋Activity佈局,而不是相對Activity的佈局位置的偏移。這個屬性的默認值是false。

      通常,在屏幕上,操作欄需要它自己的空間,並且把剩下的空間用來填充Activity的佈局。當操作欄四覆蓋模式時,Activity會使用所有的有效空間,系統會在Activity的上面描畫操作欄。如果你想要在操作欄隱藏和顯示時,佈局中的內容保持固定的尺寸好位置,那麼這種覆蓋模式是有用的。你也可能只是爲了顯示效果來使用它,因爲你可以給操作欄設置半透明的背景,以便用戶依然能夠看到操作欄背後的Activity佈局。

       注意:默認情況下,Holo主題會用半透明背景來描畫操作欄。但是,你能夠用自己的樣式來修改它,並且默認的情況下,DeviceDefault主題在不同的設備上可能使用不透明的背景。

       覆蓋模式被啓用時,Activity佈局不會感知到操作欄覆蓋在它的上面,因此,在操作欄覆蓋的區域,最好不要放置一些重要的信息或UI組件。如果適合,你能夠引用平臺的actionBarSize值來決定操作欄的高度,例如,在XML佈局文件中引用這個值。

  1. <SomeView
  2.     ...
  3.     android:layout_marginTop="?android:attr/actionBarSize" />
複製代碼
你還能夠用getHeight()方法在運行時獲取操作欄的高度。如果在Activity生存週期的早期調用這個方法,那麼在調用時所反映的操作欄的高度可能不包括被堆放的操作欄(因爲導航選項標籤)。要看如何在運行時判斷操作欄總的高度(包括被堆放的操作欄),請看Honeycomb Gallery示例應用中的TitlesFragment類。

3、操作項元素
android:actionButtonStyle給操作項按鈕定義樣式資源。android:actionBarItemBackground 給每個操作項的背景定義可描畫資源(被添加在API 級別 14中)。android:itemBackground 給每個懸浮菜單項的背景定義可描畫資源。android:actionBarDivider給操作項之間的分隔線定義可描畫資源(被添加在API 級別 14中)android:actionMenuTextColor給顯示在操作項中文本定義顏色。android:actionMenuTextAppearance 給顯示在操作項中文本定義樣式資源。android:actionBarWidgetTheme給作爲操作視窗被填充到操作欄中的可視構件定義主題資源(被添加在API級別14中)。
4、導航選項標籤
android:actionBarTabStyle 給操作欄中的選項標籤定義樣式資源。android:actionBarTabBarStyle給顯示在導航選項標籤下方的細條定義樣式資源。android:actionBarTabTextStyle給導航選項標籤中的文本定義樣式資源。
5、下拉列表
android:actionDropDownStyle 給下拉導航列表定義樣式(如背景和文本樣式)。如,下例XML文件中給操作欄定義了一些定製的樣式:
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <!-- the theme applied to the application or activity -->
        <style name="CustomActivityTheme" parent="@android:style/Theme.Holo">
            <item name="android:actionBarTabTextStyle">@style/CustomTabTextStyle</item>
            <item name="android:actionBarDivider">@drawable/ab_divider</item>
            <item name="android:actionBarItemBackground">@drawable/ab_item_background</item>
        </style>

        <!-- style for the action bar tab text -->
        <style name="CustomTabTextStyle" parent="@android:style/TextAppearance.Holo">
            <item name="android:textColor">#2456c2</item>
        </style>
    </resources>

注意:一定要在<style>標籤中聲明一個父主題,這樣定製的主題可以繼承所有沒有明確聲明的樣式。在修改操作欄樣式時,使用父主題是至關重要的,它會讓你能夠簡單的覆寫你想要改變的操作欄樣式,而不影響你不想修改的樣式(如文本的外觀或操作項的邊緣)。      你能夠在清單文件中把定製的主題應用到整個應用程序或一個單獨的Activity對象,如:

<application android:theme="@style/CustomActivityTheme" ... />
6、高級樣式      如果需要比上述屬性更高級的樣式,可以在Activity的主題中包含android:actionBarStyle和android:actionBarSplitStyle屬性。這兩個屬性的每一個都指定了另一種能夠給操作欄定義各種屬性的樣式,包括帶有android:background、android:backgroundSplit、android:backgroundStacked屬性的不同背景。如果要覆蓋這些操作欄樣式,就要確保定義一個像Widget.Holo.ActionBar這樣的父操作欄樣式。例如,如果要改變操作欄背景,你可以使用下列樣式:
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <!-- the theme applied to the application or activity -->
        <style name="CustomActivityTheme" parent="@android:style/Theme.Holo">
            <item name="android:actionBarStyle">@style/MyActionBar</item>
            <!-- other activity and action bar styles here -->
        </style>

        <!-- style for the action bar backgrounds -->
        <style name="MyActionBar" parent="@android:style/Widget.Holo.ActionBar">
            <item name="android:background">@drawable/ab_background</item>
            <item name="android:backgroundStacked">@drawable/ab_background</item>
            <item name="android:backgroundSplit">@drawable/ab_split_background</item>
        </style>
    </resources>

四、詳細代碼編寫 1、整個項目中最核心的地方就是在res/values下的styles.xml文件中,這是自定義風格樣式的資源文件,styles.xml:

    <resources xmlns:android="http://schemas.android.com/apk/res/android">

        <style name="AppBaseTheme" parent="android:Theme"></style>

        <!-- 將自定義的style取名爲CustomTheme,父類爲Theme.Holo.Light,也就是說默認背景是白底黑字(如果是Theme.Holo,則默認是黑底白字) -->
        <style name="CustomTheme" parent="android:style/Theme.Holo.Light">
            <!-- 這是item的背景修改,不按時透明,按時顯示綠色  -->
            <item name="android:selectableItemBackground">@drawable/ad_selectable_background</item>
            <item name="android:actionBarTabStyle">@style/MyActionBarTabStyle</item>
            <item name="android:actionBarTabTextStyle">@style/MyActionBarTabTextStyle</item>
                    <item name="android:actionDropDownStyle">@style/MyDropDownNav</item>   
            <item name="android:dropDownListViewStyle">@style/MyDropDownListView</item>      
        </style>

        <!-- Tab選項標籤的樣式 -->
        <style name="MyActionBarTabStyle" parent="android:style/Widget.Holo.Light.ActionBar.TabView">
            <item name="android:background">@drawable/actionbar_tab_bg</item>
            <item name="android:paddingLeft">22dp</item>
            <item name="android:paddingRight">22dp</item>
        </style>

        <!-- Tab選項標籤字體的樣式 -->
        <style name="MyActionBarTabTextStyle" parent="android:style/Widget.Holo.Light.ActionBar.TabText">        
            <item name="android:textColor">#ff0000</item>
            <item name="android:textSize">12sp</item>   
        </style>

        <!-- 下拉導航外部按鈕的樣式 -->
        <style name="MyDropDownNav" parent="android:style/Widget.Holo.Light.Spinner">
            <item name="android:background">@drawable/ad_spinner_background_holo_light</item>
            <item name="android:popupBackground">@drawable/ad_menu_dropdown_panel_holo_light</item>
            <item name="android:dropDownSelector">@drawable/ad_selectable_background</item>
        </style>
       
         <!-- 下拉導航內部按鈕的樣式 -->
         <style name="MyDropDownListView" parent="android:style/Widget.Holo.ListView.DropDown">
            <item name="android:listSelector">@drawable/ad_selectable_background</item>
        </style>
       
    </resources>
2、定義好了之後,在AndroidManifest.xml清單文件中使用,可以在application中使用,這樣就會作用於每一個Activity,也可以在每一個單獨的Activity中使用,AndroidManifest.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.yangyu.myactionbar05"
        android:versionCode="1"
        android:versionName="1.0" >

        <uses-sdk
            android:minSdkVersion="11"
            android:targetSdkVersion="14" />

        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:logo="@drawable/xianjian_logo"
            android:theme="@style/CustomTheme" >
            
            <activity
                android:name="com.yangyu.myactionbar05.MainActivity"
                android:label="@string/app_name">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            
        </application>

    </manifest>
3、新建一個drawable文件夾,在文件夾下再定義幾個資源文件:<1> 用於tab選項標籤背景的修改, actionbar_tab_bg.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/ad_tab_unselected_holo" />
    <item android:state_focused="false" android:state_selected="true"  android:state_pressed="false" android:drawable="@drawable/ad_tab_selected_pressed_holo" />
    <item android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/ad_tab_selected_pressed_holo" />
    <item android:state_selected="true"  android:state_pressed="true" android:drawable="@drawable/ad_tab_selected_pressed_holo" />

</selector>
<2> ActionBar標題欄的背景漸變色,actionbar_gradient_bg.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle" >
        <gradient
            android:angle="270"
            android:endColor="#FFEFEFEF"
            android:startColor="#cc1115"
            android:type="linear" />
    </shape>
<3> 用於下拉列表背景的變換,ad_spinner_background_holo_light.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/spinner_disabled_holo_light" android:state_enabled="false"/>
        <item android:drawable="@drawable/ad_spinner_pressed_holo_light" android:state_pressed="true"/>
        <item android:drawable="@drawable/ad_spinner_focused_holo_light" android:state_focused="true" android:state_pressed="false"/>
        <item android:drawable="@drawable/spinner_default_holo_light"/>
    </selector>
<4> ActionBar標題欄上的按鈕選中時的背景顏色切換,selected_background.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle" >
        <solid android:color="#FFA4C639" />
    </shape>
ad_selectable_background.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_mediumAnimTime">
        <item android:drawable="@drawable/selected_background" android:state_pressed="true"/>
        <item android:drawable="@android:color/transparent"/>
    </selector>
4、菜單的資源文件,main_menu.xml:
    <menu xmlns:android="http://schemas.android.com/apk/res/android" >

        <!-- 自定義搜索按鈕視圖 -->
        <item
            android:id="@+id/menu_search"
            android:actionViewClass="android.widget.SearchView"
            android:showAsAction="ifRoom"
            android:title="@string/action_label_search"/>

        <!-- 刷新按鈕圖標 -->
        <item
            android:id="@+id/menu_refresh"
            android:icon="@drawable/ic_menu_refresh_holo_light"
            android:showAsAction="ifRoom"
            android:title="@string/action_label_refresh"/>

        <!-- 收藏按鈕圖標加文字 -->        
        <item
            android:id="@+id/menu_collected"
            android:icon="@drawable/ic_menu_star_holo_light"
            android:showAsAction="ifRoom|withText"
            android:title="@string/action_label_collected"/>

    </menu>
這裏的資源文件有點多,爲了節省篇幅,講解重點和難點,博主這裏就不一一列出來了,有需要的同學可以看源碼,一目瞭然。

5、主Activity程序入口類,MainActivity.java:

package com.yangyu.myactionbar05;

import android.app.ActionBar;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;

/**
* @author yangyu
*        主Activity,程序入口類
*/
public class MainActivity extends Activity {
        //定義ActionBar
        private ActionBar actionBar;
       
        //定義Handler對象
        private final Handler handler = new Handler();

        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
               
                initView();
               
                initData();
        }

        /**
         * 初始化組件
         */
        private void initView(){
                //得到ActionBar
                actionBar = getActionBar();
        }
       
        /**
         * 初始化數據
         */
        private void initData(){
                //設置ActionBar標題不顯示
                actionBar.setDisplayShowTitleEnabled(false);
               
                //設置ActionBar的背景
                actionBar.setBackgroundDrawable(getResources().getDrawable(R.drawable.actionbar_gradient_bg));
               
                //設置ActionBar左邊默認的圖標是否可用
                actionBar.setDisplayUseLogoEnabled(true);
               
                //設置導航模式爲Tab選項標籤導航模式
                actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
               
                //設置ActinBar添加Tab選項標籤
                actionBar.addTab(actionBar.newTab().setText("TAB1").setTabListener(new MyTabListener<FragmentPage1>(this,FragmentPage1.class)));
                actionBar.addTab(actionBar.newTab().setText("TAB2").setTabListener(new MyTabListener<FragmentPage2>(this,FragmentPage2.class)));
                actionBar.addTab(actionBar.newTab().setText("TAB3").setTabListener(new MyTabListener<FragmentPage3>(this,FragmentPage3.class)));
                               
        }
       
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
                getMenuInflater().inflate(R.menu.main_menu, menu);       
                return true;
        }

        @Override
        public boolean onOptionsItemSelected(final MenuItem item) {
                switch (item.getItemId()) {
                case R.id.menu_refresh:
                        //選中刷新按鈕後刷新一秒鐘
                        item.setActionView(R.layout.actionbar_progress);
                        handler.postDelayed(new Runnable() {
                                public void run() {
                                        item.setActionView(null);
                                }
                        }, 1000);
                        return true;
                }
                return super.onOptionsItemSelected(item);
        }
       
}

6、Tab選項標籤監聽接口類,MyTabListener.java:
    package com.yangyu.myactionbar05;

    import android.app.ActionBar.Tab;
    import android.app.ActionBar.TabListener;
    import android.app.Activity;
    import android.app.Fragment;
    import android.app.FragmentTransaction;

    /**
    * @author yangyu
    *  功能描述:Tab選項標籤監聽接口
    */
    public class MyTabListener<T extends Fragment> implements TabListener {
            private Fragment fragment;
           
            private final Activity mActivity;
           
            private final Class<T> mClass;
           
            public MyTabListener(Activity activity, Class<T> clz){
                    mActivity = activity;  
                   
                    mClass = clz;
            }
           
            @Override
            public void onTabSelected(Tab tab, FragmentTransaction ft) {
                    if(fragment == null){
                            fragment = Fragment.instantiate(mActivity, mClass.getName());
                            ft.add(android.R.id.content, fragment, null);        
                    }
                    ft.attach(fragment);  
            }

            @Override
            public void onTabUnselected(Tab tab, FragmentTransaction ft) {
                    if (fragment != null) {
                            ft.detach(fragment);
                    }
            }

            @Override
            public void onTabReselected(Tab tab, FragmentTransaction ft) {
                   
            }
    }
7、Fragment類,用於顯示Tab選項標籤的內容,列出其中一個,FragmentPage1.java:
package com.yangyu.myactionbar05;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class FragmentPage1 extends Fragment{

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                        Bundle savedInstanceState) {
               
                return inflater.inflate(R.layout.fragment_1, null);               
        }       
}
關於ActionBar的內容總結到這裏差不多就要結束了

感謝原作者的無私分享,本文原出處:http://www.apkbus.com/android-125933-1-1.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章