1.利用Action Bar
1.1 問題
要在應用程式中使用最新的ActionBar模式,同時保持向後相容舊裝置;此外,還要定製外觀以符合應用程式的主題。
1.2 解決方案
(API Level 7)
ActionBar在ActionBar3.0(API Level 11)SDK中被引入,但可以通過Android支援庫的AppCompat元件內的ActionBarActivity向後移植到較早的版本。使用ActionBarActivity以及AppCompat中包含的樣式和資源,就可以將操作欄放入目標平臺為Android2.1和之後版本的應用程式中。
要點:
ActionBarActivity僅在AppCompat庫中提供,AppCompat庫是Android支援庫的一部分;它不是任意平臺級別中的原生SDK的一部分。然而,目標平臺為API Level 7或之後版本的任意應用程式都可以通過包含支援庫使用此小部件。有關在專案中包含支援庫的更多資訊,請參考以下網址:http://developer.android.com/tools/support-library/index.html。
ActionBar是頂層視窗裝飾的一部分,這意味著應用程式內容始終在其下方顯示。因此,很難在ActionBar上繪製內容或對ActionBar的位置製作動畫。如果必須執行上述操作,則使用Toolbar代替傳統的ActionBar。工具欄位於佈局內部,因此可控制它的所在位置。給定工具欄引用,Activity會將此檢視視為裝飾用的ActionBar。
注意:
Toolbar在API Level21中引入,但它也在AppCompat中提供。
1.3 實現機制
下圖顯示了適當放置標準ActionBar的Activity。

帶有Up按鈕的標準Action Bar
為了將ActionBar新增到視窗裝飾,只需要對啟用的ActionBar的Activity應用某個主題。所有預設的Holo和Material原生主題都包括ActionBar,AppCompat中也是如此。請注意,ActionBar的左側是標題和副標題,右側則是一系列操作按鈕。還有一個可選的Up導航按鈕,可以啟用該按鈕以提供與Back按鈕類似的導航。我們將在後面的章節中更詳細討論這一點。
以下三段程式碼介紹瞭如何將AppCompat主題附加到Activity以實現上圖中的效果。
ActionBar主題清單<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.androidrecipes.actionbar"> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name"> <activity android:name=".SupportActionActivity" android:label="@string/label_actionbar" android:theme="@style/AppTheme"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
res/values/styles.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- 定義將應用於整個應用程式或至少應用於許多Activity的"主題" --> <style name="AppTheme" parent="@style/Theme.AppCompat.Light.DarkActionBar"> <!-- 提供裝飾主題顏色 --> <item name="colorPrimary">@color/primaryGreen</item> <item name="colorPrimaryDark">@color/darkGreen</item> <item name="colorAccent">@color/accentGreen</item> </style> </resources>
res/values/colors.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="primaryGreen">#259b24</color> <color name="darkGreen">#0a7e07</color> <color name="accentGreen">#d0f8ce</color> </resources>
通過向Activity應用Theme.AppCompat.Light.DarkActionBar,就可以使ActionBar顯示出來。我們還可以使用標準顏色主題屬性對Activity應用綠色陰影。
右側的圖示由Activity的選項選單生成,該選項選單的定義程式碼(support.xml)如下所示。本章後面將討論選項選單的使用;在此新增此選單僅是處於完整性考慮。在以下程式碼(ActionBar的設定)中,可以看到如何通過程式碼設定ActionBar的基本屬性。
res/menu/support.xml
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/action_send" android:title="@string/action_send" android:icon="@android:drawable/ic_menu_send" app:showAsAction="ifRoom" /> <item android:id="@+id/action_settings" android:title="@string/action_settings" android:orderInCategory="100" app:showAsAction="never"/> </menu>
ActionBar的設定
public class SupportActionActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActionBar actionBar = getSupportActionBar(); //通過“Up”箭頭指示符顯示主頁 actionBar.setDisplayHomeAsUpEnabled(true); //設定標題文字 actionBar.setTitle("Android Recipes"); //設定副標題文字 actionBar.setSubtitle("ActionBar Recipes"); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.support, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: Toast.makeText(this, "Home", Toast.LENGTH_SHORT).show(); default: return super.onOptionsItemSelected(item); } } }
在onCreate()中通過getSupportActionBar()獲得ActionBar的引用,並且開始設定其標題屬性。副標題是可選項,但如果未提供標題,ActionBar將顯示Activity清單中提供android:label字串。
使用setDisplayHomeAsUpEnabled()方法,可以根據需要啟用可選的Up箭頭。該箭頭用於向回導航至父Activity,通常在頂層Activity不啟用。Up按鈕的行為由應用程式定義。使用者單擊該按鈕將觸發Activity的onOptionsItemSeleted()方法幷包含android.R.id.home值。
1.自定義檢視
ActionBar還支援自定義檢視。設定自定義檢視時,該檢視顯示在標題和操作按鈕之間。如果檢視佈局填滿螢幕寬度,它將隱藏標題文字。自定義檢視不能重疊已啟用的Up按鈕。以下程式碼顯示了在ActionBar中啟用自定義檢視的Acticity。
ActionBar的自定義檢視
public class SupportActionActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActionBar actionBar = getSupportActionBar(); actionBar.setDisplayShowCustomEnabled(true); //顯示圖片取代標題 ImageView imageView = new ImageView(this); imageView.setImageResource(R.drawable.ic_launcher); imageView.setScaleType(ImageView.ScaleType.CENTER); ActionBar.LayoutParams lp = new ActionBar.LayoutParams( ActionBar.LayoutParams.MATCH_PARENT, ActionBar.LayoutParams.MATCH_PARENT); actionBar.setCustomView(imageView, lp); } }
這會將應用程式啟動圖示的圖片放入ActionBar,該位置之前顯示的是標題文字,產生的結果如下圖所示。

Action Bar的自定義檢視
2. Toolbar
當應用程式的設計要求更多德爾控制ActionBar的放置和順序時,可以使用Toolbar代替。ToolBar能代替標準的Actionbar,因此必須對從視窗裝飾中移除ActionBar的Activity應用主題。
ToolBar的Activity清單
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.androidrecipes.actionbar" android:versionCode="1" android:versionName="1.0"> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name"> <activity android:name=".SupportToolbarActivity" android:label="@string/label_toolbar" android:theme="@style/AppToolbarTheme"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
res/values/styles.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- Toolbar代替標準的Action Bar, 因此必須對從視窗裝飾中移除Action Bar的Activity應用主題 --> <style name="AppToolbarTheme" parent="@style/Theme.AppCompat.Light.NoActionBar"> <!-- 提供裝飾主題顏色 --> <item name="colorPrimary">@color/primaryGreen</item> <item name="colorPrimaryDark">@color/darkGreen</item> <item name="colorAccent">@color/accentGreen</item> </style> </resources>
在本例中,樣式主題繼承Theme.AppCompat.Light.NoActionBar,後者禁用視窗中的預設ActionBar;我們將使用自己的Toolbar代替它。以下程式碼顯示了ToolbarActivity的佈局。
res/layout/activity_toolbar.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_height="wrap_content" android:layout_width="match_parent" android:minHeight="?attr/actionBarSize" android:background="?attr/colorPrimary" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/> <!-- 此處加入其他的應用程式檢視內容 --> </LinearLayout>
Toolbar小部件必須位於檢視層次結構中的某個位置,通常是在檢視的頂部。Toolbar不會自動接收主題樣式,因此需要將背景色設定為當前啟用主題中的colorPrimary屬性。我們還必須向Toolbar傳遞主題屬性,Toolbar使用此屬性樣式化它建立的擴充套件資源,如操作按鈕和彈出列表選單。ThemeOverlay.AppCompat.Dark.ActionBar是特殊的“重疊”主題的一部分,AppCompat提供該類以僅應用ActionBar或Toolbar所需的元素樣式化其內容元件。
以下程式碼顯示了將上述內容結合在一起的Activity程式碼。
ToolBarActivity
public class SupportToolbarActivity extends ActionBarActivity { private Toolbar mToolbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_toolbar); //必須將Toolbar的所在位置告訴Activity mToolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(mToolbar); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); /* * 使用Toolbar,必須在onCreate()之後設定標題文字; * 否則預設標籤將覆蓋我們的設定 */ //設定標題文字 mToolbar.setTitle("Android Recipes"); //設定副標題文字 mToolbar.setSubtitle("Toolbar Recipes"); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.support, menu); return true; } }
在onCreate()內部,我們負責通過setSupportActionBar()向Activity傳遞佈局內Toolbar的引用。儘管該方法的命名很含糊,但它確實需要ToolBar作為引數。這就可以使Activity向檢視應用選項選單和其他特定項。
在使用Toolbar時,我們必須對前一個示例進行移除修改。Activity實現在OnCreate()完成後設定Toolbar例項的標題值。這意味著在onCreate()中設定的任何標題將重置為清單的android:label值。為抵消這種行為,我們必須在onPostCreate()中進行修改以使改動得以保持。
如果執行此Activity,其外觀如圖(帶有Up按鈕的標準Action Bar)所示。本章後面將給出不同UI範例如何傾向於使用Toolbar而非頂層ActionBar的示例。