轉載地址:http://blog.csdn.net/xyz_lmn/article/details/8132420
添加導航選項標籤
當你想要在一個Activity中提供導航選擇標籤時,使用操作欄的選項標籤是一個非常好的選擇(而不是使用TabWidget類),因爲系統會調整操作欄選項標籤來適應不同尺寸的屏幕的需要---在屏幕足夠寬的時候,導航選項標籤會被放到主操作欄中;當屏幕太窄的時候,選項標籤會被放到一個分離的橫條中,如圖9和圖10所示。
圖9. Honeycomb Gallery應用程序中的操作欄選項標籤的截圖
圖10. 在窄屏設備上被堆放在操作欄中的選項標籤的截屏
要使用選項標籤在Fragmengt之間切換,你必須在每次選擇一個選項標籤時執行一個Fragment事務。如果你不熟悉如何使用FragmentTransaction對象來改變Fragment,請閱讀Fragment開發指南。
首先,你的佈局必須包含一個用於放置跟每個Fragment對象關聯的選項標籤的ViewGroup對象。並且要確保這個ViewGroup對象有一個資源ID,以便你能夠在選項標籤的切換代碼中能夠引用它。另外,如果選項標籤的內容填充在Activity的佈局中(不包括操作欄),那麼Activity不需要任何佈局(你甚至不需要調用setContentView()方法)。相反,你能夠把每個Fragment對象放到默認的根ViewGroup對象中,你能夠用android.R.id.content ID來引用這個ViewGroup對象(在Fragment執行事務期間,你能夠在下面的示例代碼中看到如何使用這個ID的。
決定了Fragment對象在佈局中的顯示位置後,添加選項標籤的基本過程如下:
1. 實現ActionBar.TabListener接口。這個接口中回調方法會響應選項標籤上的用戶事件,以便你能夠切換Fragment對象;
2. 對於每個要添加的選項標籤,都要實例化一個ActionBar.Tab對象,並且調用setTabListener()方法設置ActionBar.Tab對象的事件監聽器。還可以用setText()或setIcon()方法來設置選項標籤的標題或圖標。
3. 通過調用addTab()方法,把每個選項標籤添加到操作欄。
在查看ActionBar.TabListener接口時,注意到回調方法只提供了被選擇的ActionBar.Tab對象和執行Fragment對象事務的FragmentTransaction對象---沒有說明任何有關Fragment切換的事。因此。你必須定義自己的每個ActionBar.Tab之間的關聯,以及ActionBar.Tab所代表的適合的Fragment對象(爲了執行合適的Fragment事務)。依賴你的設計,會有幾種不同的方法來定義這種關聯。在下面的例子中,ActionBar.TabListener接口的實現提供了一個構造器,這樣每個新的選項標籤都會使用它自己的監聽器實例。每個監聽器實例都定義了幾個在對應Fragment對象上執行事務時必須的幾個成員變量。
例如,以下示例是ActionBar.TabListener接口的一種實現,在這個實現中,每個選項標籤都使用了它自己的監聽器實例:
public static class TabListener<T extends Fragment> implements ActionBar.TabListener {
private Fragment mFragment;
private final Activity mActivity;
private final String mTag;
private final Class<T> mClass;
/** Constructor used each time a new tab is created.
* @param activity The host Activity, used to instantiate the fragment
* @param tag The identifier tag for the fragment
* @param clz The fragment's Class, used to instantiate the fragment
*/
public TabListener(Activity activity, String tag, Class<T> clz) {
mActivity = activity;
mTag = tag;
mClass = clz;
}
/* The following are each of the ActionBar.TabListener callbacks */
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// Check if the fragment is already initialized
if (mFragment == null) {
// If not, instantiate and add it to the activity
mFragment = Fragment.instantiate(mActivity, mClass.getName());
ft.add(android.R.id.content, mFragment, mTag);
} else {
// If it exists, simply attach it in order to show it
ft.attach(mFragment);
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if (mFragment != null) {
// Detach the fragment, because another one is being attached
ft.detach(mFragment);
}
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// User selected the already selected tab. Usually do nothing.
}
}
警告:針對每個回調中的Fragment事務,你都不必調用commit()方法---系統會調用這個方法,並且如果你自己調用了這個方法,有可能會拋出一個異常。你也不能把這些Fragment事務添加到回退堆棧中。
在這個例子中,當對應的選項標籤被選擇時,監聽器只是簡單的把一個Fragment對象附加(attach()方法)到Activity佈局上---或者,如果沒有實例化,就會創建這個Fragment對象,並且把它添加(add()方法)到佈局中(android.R.id.content ViewGroup的一個子類),當這個選項標籤解除選擇時,對應的Fragment對象也會被解除與佈局的依附關係。
ActionBar.TabListener的實現做了大量的工作,剩下的事情就是創建每個ActionBar.Tab對象並把它添加到ActionBar對象中,另外,你必須調用setNavigationMode(NAVIGATION_MODE_TABS)方法來讓選項標籤可見。如果選項標籤的標題實際指示了當前的View對象,你也可以通過調用setDisplayShowTitleEnabled(false)方法來禁用Activity的標題。
例如,下面的代碼使用上面定義的監聽器在操作欄中添加了兩個選項標籤。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Notice that setContentView() is not used, because we use the root
// android.R.id.content as the container for each fragment
// setup action bar for tabs
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayShowTitleEnabled(false);
Tab tab = actionBar.newTab()
.setText(R.string.artist)
.setTabListener(new TabListener<ArtistFragment>(
this, "artist", ArtistFragment.class));
actionBar.addTab(tab);
tab = actionBar.newTab()
.setText(R.string.album)
.setTabListener(new TabListener<AlbumFragment>(
this, "album", AlbumFragment.class));
actionBar.addTab(tab);
}
注意:以上有關ActionBar.TabListener的實現,只是幾種可能的技術之一。在API Demos應用中你能夠看到更多的這種樣式。
如果Activity終止了,那麼你應該保存當前選擇的選項標籤的狀態,以便當用戶再次返回時,你能夠打開合適的選項標籤。在保存狀態的時刻,你能夠用getSelectedNavigationIndex()方法查詢當前的被選擇的選項標籤。這個方法返回被選擇的選項標籤的索引位置。
警告:保存每個Fragment所必須的狀態是至關重要的,因爲當用戶用選項標籤在Fragment對象間切換時,它會查看Fragment在離開時樣子。
注意:在某些情況下,Android系統會把操作欄選項標籤作爲一個下拉列表來顯示,以便確保操作欄的最優化顯示。
添加下拉式導航
作爲Activity內部的另一種導航(或過濾)模式,操作欄提供了內置的下拉列表。下拉列表能夠提供Activity中內容的不同排序模式。
啓用下拉式導航的基本過程如下:
1. 創建一個給下拉提供可選項目的列表,以及描畫列表項目時所使用的佈局;
2. 實現ActionBar.OnNavigationListener回調,在這個回調中定義當用戶選擇列表中一個項目時所發生的行爲;
3. 用setNavigationMode()方法該操作欄啓用導航模式,如:
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
4. 用setListNavigationCallbacks()方法給下拉列表設置回調方法,如:
1)actionBar.setListNavigationCallbacks(mSpinnerAdapter, mNavigationCallback);
這個方法需要SpinnerAdapter和ActionBar.OnNavigationListener對象。下面是 SpinnerAdapter
and ActionBar.OnNavigationListener
的例子。
Example SpinnerAdapter and OnNavigationListener
設置操作欄的樣式
如果你對應用程序中的可視構件進行了定製化的設計,那麼你可能也會要對操作欄做一些重新設計,以便跟應用程序的設計匹配。要這樣做的話,需要使用Android的樣式與主題框架中的一些特殊的樣式屬性來重新設置操作欄的樣式。
注意:改變外觀的背景圖片依賴與當前按鈕的狀態(選擇、按下、解除選擇),因此你使用的可描畫的資源必須是一個可描畫的狀態列表。
警告:對於你提供的所有可描畫的背景,要確保使用NinePatch類型可描畫資源,以便允許圖片的拉伸。NinePatch類型的圖片應該比40像素高30像素寬的圖片要小。
普通的外觀
android:windowActionBarOverlay
這個屬性聲明瞭操作欄是否應該覆蓋Activity佈局,而不是相對Activity的佈局位置的偏移。這個屬性的默認值是false。
通常,在屏幕上,操作欄需要它自己的空間,並且把剩下的空間用來填充Activity的佈局。當操作欄四覆蓋模式時,Activity會使用所有的有效空間,系統會在Activity的上面描畫操作欄。如果你想要在操作欄隱藏和顯示時,佈局中的內容保持固定的尺寸好位置,那麼這種覆蓋模式是有用的。你也可能只是爲了顯示效果來使用它,因爲你可以給操作欄設置半透明的背景,以便用戶依然能夠看到操作欄背後的Activity佈局。
注意:默認情況下,Holo主題會用半透明背景來描畫操作欄。但是,你能夠用自己的樣式來修改它,並且默認的情況下,DeviceDefault主題在不同的設備上可能使用不透明的背景。
覆蓋模式被啓用時,Activity佈局不會感知到操作欄覆蓋在它的上面,因此,在操作欄覆蓋的區域,最好不要放置一些重要的信息或UI組件。如果適合,你能夠引用平臺的actionBarSize值來決定操作欄的高度,例如,在XML佈局文件中引用這個值。
[html] view plaincopyprint?
<SomeView
...
android:layout_marginTop="?android:attr/actionBarSize" />
你還能夠用getHeight()方法在運行時獲取操作欄的高度。如果在Activity生存週期的早期調用這個方法,那麼在調用時所反映的操作欄的高度可能不包括被堆放的操作欄(因爲導航選項標籤)。要看如何在運行時判斷操作欄總的高度(包括被堆放的操作欄),請看Honeycomb Gallery示例應用中的TitlesFragment類。
操作項元素
給操作項按鈕定義樣式資源。
給每個操作項的背景定義可描畫資源(被添加在API 級別 14中)。
給每個懸浮菜單項的背景定義可描畫資源。
給操作項之間的分隔線定義可描畫資源(被添加在API 級別 14中)
給顯示在操作項中文本定義顏色。
給顯示在操作項中文本定義樣式資源。
給作爲操作視窗被填充到操作欄中的可視構件定義主題資源(被添加在API級別14中)。
android:actionBarTabStyle 給操作欄中的選項標籤定義樣式資源。android:actionBarTabBarStyle給顯示在導航選項標籤下方的細條定義樣式資源。android:actionBarTabTextStyle給導航選項標籤中的文本定義樣式資源。下拉列表
android:actionDropDownStyle 給下拉導航列表定義樣式(如背景和文本樣式)。如,下例XML文件中給操作欄定義了一些定製的樣式:
[html] view plaincopyprint?
<?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" ... />
高級樣式
如果需要比上述屬性更高級的樣式,可以在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>