頂部標題欄:自定義ActionBar風格和樣式

這篇文章將對ActionBar專題前面幾篇學習過的內容作一個總結,順便運用之前學過的知識實現一個自定義樣式的ActionBar標題欄效果。話很少說,進入今天的正題。

1、實現效果圖 html

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



 

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



2、項目結構圖 app


3、編碼準備工做 框架

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

一、設置操做欄的樣式 工具

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

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

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


二、普通的外觀

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類。

三、操做項元素

android:actionButtonStyle 給操做項按鈕定義樣式資源。 android:actionBarItemBackground  給每一個操做項的背景定義可描畫資源(被添加在API 級別 14中)。 android:itemBackground  給每一個懸浮菜單項的背景定義可描畫資源。 android:actionBarDivider 給操做項之間的分隔線定義可描畫資源(被添加在API 級別 14中) android:actionMenuTextColor 給顯示在操做項中文本定義顏色。 android:actionMenuTextAppearance  給顯示在操做項中文本定義樣式資源。 android:actionBarWidgetTheme 給做爲操做視窗被填充到操做欄中的可視構件定義主題資源(被添加在API級別14中)。

四、導航選項標籤

android:actionBarTabStyle  給操做欄中的選項標籤訂義樣式資源。 android:actionBarTabBarStyle 給顯示在導航選項標籤下方的細條定義樣式資源。 android:actionBarTabTextStyle 給導航選項標籤中的文本定義樣式資源。

五、下拉列表

android:actionDropDownStyle  給下拉導航列表定義樣式(如背景和文本樣式)。 如,下例XML文件中給操做欄定義了一些定製的樣式:
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <!-- the theme applied to the application or activity -->  
  4.     <style name="CustomActivityTheme" parent="@android :style/Theme.Holo">  
  5.         <item name="android:actionBarTabTextStyle">@style/CustomTabTextStyle</item>  
  6.         <item name="android:actionBarDivider">@drawable/ab_divider</item>  
  7.         <item name="android:actionBarItemBackground">@drawable/ab_item_background</item>  
  8.     </style>  
  9.   
  10.     <!-- style for the action bar tab text -->  
  11.     <style name="CustomTabTextStyle" parent="@android :style/TextAppearance.Holo">  
  12.         <item name="android:textColor">#2456c2</item>  
  13.     </style>  
  14. </resources>  

        注意:必定要在<style>標籤中聲明一個父主題,這樣定製的主題能夠繼承全部沒有明確聲明的樣式。在修改操做欄樣式時,使用父主題是相當重要的,它會讓你可以簡單的覆寫你想要改變的操做欄樣式,而不影響你不想修改的樣式(如文本的外觀或操做項的邊緣)。

      你可以在清單文件中把定製的主題應用到整個應用程序或一個單獨的Activity對象,如:

  1. <application android:theme="@style/CustomActivityTheme" ... />  

六、高級樣式

      若是須要比上述屬性更高級的樣式,能夠在Activity的主題中包含android:actionBarStyle和 android:actionBarSplitStyle屬性。這兩個屬性的每個都指定了另外一種可以給操做欄定義各類屬性的樣式,包括帶有 android:background、android:backgroundSplit、android:backgroundStacked屬性的不 同背景。若是要覆蓋這些操做欄樣式,就要確保定義一個像Widget.Holo.ActionBar這樣的父操做欄樣式。

例如,若是要改變操做欄背景,你可使用下列樣式:

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <!-- the theme applied to the application or activity -->  
  4.     <style name="CustomActivityTheme" parent="@android:style/Theme.Holo">  
  5.         <item name="android:actionBarStyle">@style/MyActionBar</item>  
  6.         <!-- other activity and action bar styles here -->  
  7.     </style>  
  8.   
  9.     <!-- style for the action bar backgrounds -->  
  10.     <style name="MyActionBar" parent="@android:style/Widget.Holo.ActionBar">  
  11.         <item name="android:background">@drawable/ab_background</item>  
  12.         <item name="android:backgroundStacked">@drawable/ab_background</item>  
  13.         <item name="android:backgroundSplit">@drawable/ab_split_background</item>  
  14.     </style>  
  15. </resources>  

4、詳細代碼編寫

 

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

  1. <resources xmlns:android="http://schemas.android.com/apk/res/android">  
  2.   
  3.     <style name="AppBaseTheme" parent="android:Theme"></style>  
  4.   
  5.     <!-- 將自定義的style取名爲CustomTheme,父類爲Theme.Holo.Light,也就是說默認背景是白底黑字(若是是Theme.Holo,則默認是黑底白字) -->  
  6.     <style name="CustomTheme" parent="android:style/Theme.Holo.Light">  
  7.         <!-- 這是item的背景修改,不按時透明,按時顯示綠色  -->  
  8.         <item name="android:selectableItemBackground">@drawable/ad_selectable_background</item>  
  9.         <item name="android:actionBarTabStyle">@style/MyActionBarTabStyle</item>  
  10.         <item name="android:actionBarTabTextStyle">@style/MyActionBarTabTextStyle</item>  
  11.         <item name="android:actionDropDownStyle">@style/MyDropDownNav</item>     
  12.         <item name="android:dropDownListViewStyle">@style/MyDropDownListView</item>         
  13.     </style>  
  14.   
  15.     <!-- Tab選項標籤的樣式 -->  
  16.     <style name="MyActionBarTabStyle" parent="android:style/Widget.Holo.Light.ActionBar.TabView">  
  17.         <item name="android:background">@drawable/actionbar_tab_bg</item>  
  18.         <item name="android:paddingLeft">22dp</item>  
  19.         <item name="android:paddingRight">22dp</item>  
  20.     </style>  
  21.   
  22.     <!-- Tab選項標籤字體的樣式 -->  
  23.     <style name="MyActionBarTabTextStyle" parent="android:style/Widget.Holo.Light.ActionBar.TabText">          
  24.         <item name="android:textColor">#ff0000</item>  
  25.         <item name="android:textSize">12sp</item>     
  26.     </style>  
  27.   
  28.     <!-- 下拉導航外部按鈕的樣式 -->  
  29.     <style name="MyDropDownNav" parent="android:style/Widget.Holo.Light.Spinner">  
  30.         <item name="android:background">@drawable/ad_spinner_background_holo_light</item>  
  31.         <item name="android:popupBackground">@drawable/ad_menu_dropdown_panel_holo_light</item>  
  32.         <item name="android:dropDownSelector">@drawable/ad_selectable_background</item>  
  33.     </style>  
  34.       
  35.      <!-- 下拉導航內部按鈕的樣式 -->  
  36.      <style name="MyDropDownListView" parent="android:style/Widget.Holo.ListView.DropDown">  
  37.         <item name="android:listSelector">@drawable/ad_selectable_background</item>  
  38.     </style>  
  39.       
  40. </resources>  

二、定義好了以後,在AndroidManifest.xml清單文件中使用,能夠在application中使用,這樣就會做用於每個Activity,也能夠在每個單獨的Activity中使用,AndroidManifest.xml:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.yangyu.myactionbar05"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk  
  8.         android:minSdkVersion="11"  
  9.         android:targetSdkVersion="14" />  
  10.   
  11.     <application  
  12.         android:allowBackup="true"  
  13.         android:icon="@drawable/ic_launcher"  
  14.         android:label="@string/app_name"  
  15.         android:logo="@drawable/xianjian_logo"  
  16.         android:theme="@style/CustomTheme" >  
  17.           
  18.         <activity  
  19.             android:name="com.yangyu.myactionbar05.MainActivity"   
  20.             android:label="@string/app_name">  
  21.             <intent-filter>  
  22.                 <action android:name="android.intent.action.MAIN" />  
  23.                 <category android:name="android.intent.category.LAUNCHER" />  
  24.             </intent-filter>  
  25.         </activity>  
  26.           
  27.     </application>  
  28.   
  29. </manifest>  

三、新建一個drawable文件夾,在文件夾下再定義幾個資源文件:

<1> 用於tab選項標籤背景的修改, actionbar_tab_bg.xml:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">  
  3.   
  4.     <item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/ad_tab_unselected_holo" />  
  5.     <item android:state_focused="false" android:state_selected="true"  android:state_pressed="false" android:drawable="@drawable/ad_tab_selected_pressed_holo" />  
  6.     <item android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/ad_tab_selected_pressed_holo" />  
  7.     <item android:state_selected="true"  android:state_pressed="true" android:drawable="@drawable/ad_tab_selected_pressed_holo" />  
  8.   
  9. </selector>  
<2> ActionBar標題欄的背景漸變色,actionbar_gradient_bg.xml:
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:shape="rectangle" >  
  4.   
  5.     <gradient  
  6.         android:angle="270"  
  7.         android:endColor="#FFEFEFEF"  
  8.         android:startColor="#cc1115"  
  9.         android:type="linear" />  
  10.   
  11. </shape>  

<3> 用於下拉列表背景的變換,ad_spinner_background_holo_light.xml:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">  
  3.   
  4.     <item android:drawable="@drawable/spinner_disabled_holo_light" android:state_enabled="false"/>  
  5.     <item android:drawable="@drawable/ad_spinner_pressed_holo_light" android:state_pressed="true"/>  
  6.     <item android:drawable="@drawable/ad_spinner_focused_holo_light" android:state_focused="true" android:state_pressed="false"/>  
  7.     <item android:drawable="@drawable/spinner_default_holo_light"/>  
  8.   
  9. </selector>  

<4> ActionBar標題欄上的按鈕選中時的背景顏色切換,

selected_background.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:shape="rectangle" >  
  4.   
  5.     <solid android:color="#FFA4C639" />  
  6.   
  7. </shape>  
ad_selectable_background.xml:
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_mediumAnimTime">  
  3.   
  4.     <item android:drawable="@drawable/selected_background" android:state_pressed="true"/>  
  5.     <item android:drawable="@android:color/transparent"/>  
  6.   
  7. </selector>  

四、菜單的資源文件,main_menu.xml:

  1. <menu xmlns:android="http://schemas.android.com/apk/res/android" >  
  2.   
  3.     <!-- 自定義搜索按鈕視圖 -->  
  4.     <item  
  5.         android:id="@+id/menu_search"  
  6.         android:actionViewClass="android.widget.SearchView"  
  7.         android:showAsAction="ifRoom"  
  8.         android:title="@string/action_label_search"/>  
  9.   
  10.     <!-- 刷新按鈕圖標 -->  
  11.     <item  
  12.         android:id="@+id/menu_refresh"  
  13.         android:icon="@drawable/ic_menu_refresh_holo_light"  
  14.         android:showAsAction="ifRoom"  
  15.         android:title="@string/action_label_refresh"/>  
  16.   
  17.     <!-- 收藏按鈕圖標加文字 -->          
  18.     <item  
  19.         android:id="@+id/menu_collected"  
  20.         android:icon="@drawable/ic_menu_star_holo_light"  
  21.         android:showAsAction="ifRoom|withText"  
  22.         android:title="@string/action_label_collected"/>  
  23.   
  24. </menu>  
            這裏的資源文件有點多,爲了節省篇幅,講解重點和難點,博主這裏就不一一列出來了,有須要的同窗能夠看源碼,一目瞭然。

五、主Activity程序入口類,MainActivity.java:
  1. package com.yangyu.myactionbar05;  
  2.   
  3. import android.app.ActionBar;  
  4. import android.app.Activity;  
  5. import android.os.Bundle;  
  6. import android.os.Handler;  
  7. import android.view.Menu;  
  8. import android.view.MenuItem;  
  9.   
  10. /** 
  11.  * @author yangyu 
  12.  *  主Activity,程序入口類 
  13.  */  
  14. public class MainActivity extends Activity {  
  15.     //定義ActionBar  
  16.     private ActionBar actionBar;  
  17.       
  18.     //定義Handler對象  
  19.     private final Handler handler = new Handler();  
  20.   
  21.     @Override  
  22.     protected void onCreate(Bundle savedInstanceState) {  
  23.         super.onCreate(savedInstanceState);  
  24.         setContentView(R.layout.activity_main);  
  25.           
  26.         initView();  
  27.           
  28.         initData();  
  29.     }  
  30.   
  31.     /** 
  32.      * 初始化組件 
  33.      */  
  34.     private void initView(){  
  35.         //獲得ActionBar  
  36.         actionBar = getActionBar();  
  37.     }  
  38.       
  39.     /** 
  40.      * 初始化數據 
  41.      */  
  42.     private void initData(){  
  43.         //設置ActionBar標題不顯示  
  44.         actionBar.setDisplayShowTitleEnabled(false);  
  45.           
  46.         //設置ActionBar的背景  
  47.         actionBar.setBackgroundDrawable(getResources().getDrawable(R.drawable.actionbar_gradient_bg));  
  48.           
  49.         //設置ActionBar左邊默認的圖標是否可用  
  50.         actionBar.setDisplayUseLogoEnabled(true);  
  51.           
  52.         //設置導航模式爲Tab選項標籤導航模式  
  53.         actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);  
  54.           
  55.         //設置ActinBar添加Tab選項標籤  
  56.         actionBar.addTab(actionBar.newTab().setText("TAB1").setTabListener(new MyTabListener<FragmentPage1>(this,FragmentPage1.class)));  
  57.         actionBar.addTab(actionBar.newTab().setText("TAB2").setTabListener(new MyTabListener<FragmentPage2>(this,FragmentPage2.class)));  
  58.         actionBar.addTab(actionBar.newTab().setText("TAB3").setTabListener(new MyTabListener<FragmentPage3>(this,FragmentPage3.class)));  
  59.                   
  60.     }  
  61.       
  62.     @Override  
  63.     public boolean onCreateOptionsMenu(Menu menu) {  
  64.         getMenuInflater().inflate(R.menu.main_menu, menu);    
  65.         return true;  
  66.     }  
  67.   
  68.     @Override  
  69.     public boolean onOptionsItemSelected(final MenuItem item) {  
  70.         switch (item.getItemId()) {  
  71.         case R.id.menu_refresh:  
  72.             //選中刷新按鈕後刷新一秒鐘  
  73.             item.setActionView(R.layout.actionbar_progress);  
  74.             handler.postDelayed(new Runnable() {  
  75.                 public void run() {  
  76.                     item.setActionView(null);  
  77.                 }  
  78.             }, 1000);  
  79.             return true;  
  80.         }  
  81.         return super.onOptionsItemSelected(item);  
  82.     }  
  83.       
  84. }  

六、Tab選項標籤監聽接口類,MyTabListener.java:

  1. package com.yangyu.myactionbar05;  
  2.   
  3. import android.app.ActionBar.Tab;  
  4. import android.app.ActionBar.TabListener;  
  5. import android.app.Activity;  
  6. import android.app.Fragment;  
  7. import android.app.FragmentTransaction;  
  8.   
  9. /** 
  10.  * @author yangyu 
  11.  *  功能描述:Tab選項標籤監聽接口 
  12.  */  
  13. public class MyTabListener<T extends Fragment> implements TabListener {  
  14.     private Fragment fragment;  
  15.       
  16.     private final Activity mActivity;  
  17.       
  18.     private final Class<T> mClass;  
  19.       
  20.     public MyTabListener(Activity activity, Class<T> clz){  
  21.         mActivity = activity;    
  22.           
  23.         mClass = clz;   
  24.     }  
  25.       
  26.     @Override  
  27.     public void onTabSelected(Tab tab, FragmentTransaction ft) {  
  28.         if(fragment == null){  
  29.             fragment = Fragment.instantiate(mActivity, mClass.getName());  
  30.             ft.add(android.R.id.content, fragment, null);     
  31.         }  
  32.         ft.attach(fragment);    
  33.     }  
  34.   
  35.     @Override  
  36.     public void onTabUnselected(Tab tab, FragmentTransaction ft) {  
  37.         if (fragment != null) {  
  38.             ft.detach(fragment);  
  39.         }  
  40.     }  
  41.   
  42.     @Override  
  43.     public void onTabReselected(Tab tab, FragmentTransaction ft) {  
  44.           
  45.     }  
  46. }  
  47.  

七、Fragment類,用於顯示Tab選項標籤的內容,列出其中一個,FragmentPage1.java:

  1. package com.yangyu.myactionbar05;  
  2.   
  3. import android.app.Fragment;  
  4. import android.os.Bundle;  
  5. import android.view.LayoutInflater;  
  6. import android.view.View;  
  7. import android.view.ViewGroup;  
  8.   
  9. public class FragmentPage1 extends Fragment{  
  10.   
  11.     @Override  
  12.     public View onCreateView(LayoutInflater inflater, ViewGroup container,  
  13.             Bundle savedInstanceState) {  
  14.           
  15.         return inflater.inflate(R.layout.fragment_1, null);       
  16.     }     
  17. }  
相關文章
相關標籤/搜索