Action Bar
操作栏是一个窗口功能,可识别用户的位置,并提供用户操作和导航模式。使用操作栏,您的用户在不同应用程序熟悉的界面,该系统正常适应不同的屏幕配置。
图1.一个操作栏,其中包括[1]应用程序图标,[2]两项行动项目,和[3]操作溢出。
操作栏提供了几个关键功能:
提供了应用程序给你的应用的身份,并表示用户位置的专用空间。
使重要行动显明易在可预见的方式(如搜索)。
支持应用内一致的导航和查看开关(带标签或下拉列表)。
有关操作栏中的互动模式和设计准则的详细信息,请参阅操作栏的设计指南。
在Android 3.0的(API级别11)首先添加的动作条的API,但他们也可以在支持图书馆与Android 2.1(API 7级)及以上的兼容性。
本指南重点介绍如何使用支持库行动起来吧,但如果您的应用程序仅支持的Android 3.0或更高版本,您应在框架使用的ActionBar的API。大部分的API都是相同的,但居住在不同的包命名空间有几个例外到在下面的章节提到的方法名称或签名。
注意:务必从相应的包导入动作条类(及相关API):
如果低于11支持API级别:
import android.support.v7.app.ActionBar
如果只支持API级别11和更高版本:
import android.app.ActionBar
注意:如果你正在寻找关于上下文显示行动项目上下文操作栏的信息,请参阅菜单指南。
添加操作栏
如上所述,本指南重点介绍如何在支持库使用的ActionBar的API。所以,如果你可以添加操作栏,则必须按照在支持库设置的指示成立了以应用程序兼容性V7支持库项目。
一旦你的项目设置与支持库,这里是如何添加操作栏:
通过扩展ActionBarActivity创建活动。
使用(或扩展)的Theme.AppCompat主题,为您的活动之一。 例如:
<activity android:theme="@style/Theme.AppCompat.Light" ... >现在,你的活动在Android2.1(API7级)以上运行时,包括操作栏。
ActionBar actionBar = getSupportActionBar()
;
actionBar.hide();
在API级别11或更高版本
res/menu/main_activity_actions.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/action_search" android:icon="@drawable/ic_action_search" android:title="@string/action_search"/> <item android:id="@+id/action_compose" android:icon="@drawable/ic_action_compose" android:title="@string/action_compose" /> </menu>然后在你的活动onCreateOptionsMenu()方法,填充菜单资源到给定的菜单到每个项目添加到操作栏:
@Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu items for use in the action bar MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main_activity_actions, menu); return super.onCreateOptionsMenu(menu); }要申请一个项目操作栏中的操作按钮直接显示,包括在<item>标签showAsAction=“ifRoom”。 例如:
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:yourapp="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/action_search" android:icon="@drawable/ic_action_search" android:title="@string/action_search" yourapp:showAsAction="ifRoom" /> ... </menu>如果没有足够的空间,在操作栏中的项目,它会出现在动作溢出。
<item yourapp:showAsAction="ifRoom|withText" ... />注:“withText”值是一个提示文本标题应该出现在动作条。可能的情况下操作栏将显示标题,但可能不会,如果一个图标可用并且操作栏被约束的空间。
@Override public boolean onOptionsItemSelected(MenuItem item) { // Handle presses on the action bar items switch (item.getItemId()) { case R.id.action_search: openSearch(); return true; case R.id.action_compose: composeMessage(); return true; default: return super.onOptionsItemSelected(item); } }注意:如果从一个片段膨胀的菜单项,通过碎片类的onCreateOptionsMenu()回调,系统调用onOptionsItemSelected()为片段,当用户选择这些项目中的一个。然而,活动都有机会第一处理该事件,因此,系统首先在活动呼叫onOptionsItemSelected(),要求该片段在同一回调之前。为了确保在活动的任何片段也有机会来处理回调,总是调用传递给超类的默认行为,而不是返回false时,你不处理的项目。
图3.实体模型显示制表符(左)的操作栏,然后拆分操作栏(中);与应用程序图标和标题禁用(右)。
使用拆分操作栏
拆分操作栏在屏幕的底部提供了一个独立的酒吧时显示活动的窄屏幕(如面向肖象的手机)上运行的所有行动项目。
分离行动项目这种方式保证了空间的合理数量可显示一个狭窄的屏幕上你所有的行动项目,同时留出空间在顶部导航和标题元素。
要使用支持库时启用拆分行动起来吧,你必须做两件事情:
添加uiOptions=“splitActionBarWhenNarrow”每个<活动>元素或<application>元素。此属性是API14级及更高版本(它是由旧版本忽略)只听懂。
为了支持旧版本中,添加<元数据>元素每个<活动>元素声明了“android.support.UI OPTIONS”同等价值的一个孩子。
例如:
<manifest ...> <activity uiOptions="splitActionBarWhenNarrow" ... > <meta-data android:name="android.support.UI_OPTIONS" android:value="splitActionBarWhenNarrow" /> </activity> </manifest>采用分体式操作栏也可以让导航选项卡崩溃到主操作栏,如果你删除的图标和标题(如图3所示右侧)。要产生这种效果,禁用操作栏图标和标题与setDisplayShowHomeEnabled(假)和setDisplayShowTitleEnabled(假)。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_details); ActionBar actionBar = getSupportActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); ... }现在,在操作栏中的图标出现在向上插入符号(如图4所示)。然而,它不会做默认任何事情。指定活动在用户按下向上按钮打开,你有两个选择:
<application ... > ... <!-- The main/home activity (has no parent activity) --> <activity android:name="com.example.myfirstapp.MainActivity" ...> ... </activity> <!-- A child of the main activity --> <activity android:name="com.example.myfirstapp.DisplayMessageActivity" android:label="@string/title_activity_display_message" android:parentActivityName="com.example.myfirstapp.MainActivity" > <!-- Parent activity meta-data to support API level 7+ --> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.example.myfirstapp.MainActivity" /> </activity> </application>一旦父活动在这样的清单中指定并启用与setDisplayHomeAsUpEnabled(向上按钮),你的工作就完成了,并在操作栏中正确导航了。
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:yourapp="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/action_search" android:title="@string/action_search" android:icon="@drawable/ic_action_search" yourapp:showAsAction="ifRoom|collapseActionView" yourapp:actionViewClass="android.support.v7.widget.SearchView" /> </menu>请注意,showAsAction属性还包括“collapseActionView”的价值。这是可选的,并宣布行动视图应该被折叠成一个按钮。 (此行为有关处理湿陷性行动享有以下部分进一步说明。)
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main_activity_actions, menu); MenuItem searchItem = menu.findItem(R.id.action_search); SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem); // Configure the search info and add any event listeners ... return super.onCreateOptionsMenu(menu); }在API级别11或更高版本
menu.findItem(R.id.action_search).getActionView()有关使用搜索小插件的详细信息,请参阅创建一个搜索界面。
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.options, menu); MenuItem menuItem = menu.findItem(R.id.actionItem); ... // When using the support library, the setOnActionExpandListener() method is // static and accepts the MenuItem object as an argument MenuItemCompat.setOnActionExpandListener(menuItem, new OnActionExpandListener() { @Override public boolean onMenuItemActionCollapse(MenuItem item) { // Do something when collapsed return true; // Return true to collapse action view } @Override public boolean onMenuItemActionExpand(MenuItem item) { // Do something when expanded return true; // Return true to expand action view } }); }增加一个动作提供商
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:yourapp="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/action_share" android:title="@string/share" yourapp:showAsAction="ifRoom" yourapp:actionProviderClass="android.support.v7.widget.ShareActionProvider" /> ... </menu>现在的动作提供商采取的操作项目的控制,并可以处理它的外观和行为。但你还是必须提供当它出现在动作溢出用于该项目的标题。
private ShareActionProvider mShareActionProvider;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_activity_actions, menu);
// Set up ShareActionProvider's default share intent
MenuItem shareItem = menu.findItem(R.id.action_share);
mShareActionProvider = (ShareActionProvider)
MenuItemCompat.getActionProvider(shareItem);
mShareActionProvider.setShareIntent(getDefaultIntent());
return super.onCreateOptionsMenu(menu);
}
/** Defines a default (dummy) share intent to initialize the action provider.
* However, as soon as the actual content to be used in the intent
* is known or changes, you must update the share intent by again calling
* mShareActionProvider.setShareIntent()
*/
private Intent getDefaultIntent() {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/*");
return intent;
}
该ShareActionProvider现在处理与该项目的所有用户交互和你不需要处理单击从onOptionsItemSelected()回调方法事件。
public View onCreateActionView(MenuItem forItem) { // Inflate the action view to be shown on the action bar. LayoutInflater layoutInflater = LayoutInflater.from(mContext); View view = layoutInflater.inflate(R.layout.action_provider, null); ImageButton button = (ImageButton) view.findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Do something... } }); return view; }onPerformDefaultAction()
图7.宽屏幕上操作栏标签。
设计指南
标签
另请参阅
创建具有选项卡刷卡次数
图狭窄的屏幕上8标签。
操作栏中的标签很容易让用户探索,并在您的应用程序不同的视图之间切换。因为他们适应不同屏幕尺寸的动作条提供的标签是理想的。例如,当屏幕是足够宽的标签显示在操作栏旁边的操作按钮(例如,当在一个片剂,在图7中示出),而当一个窄屏幕上它们出现在一个独立的杆(称为“堆栈操作栏”,如图8所示)。在某些情况下,Android系统将改为显示您的选项卡项目作为一个下拉列表,以确保操作栏中的最佳选择。
要开始,你的布局必须包含在其中放置一个标签相关联的每个片段的ViewGroup。请确保ViewGroup中有一个资源的ID,这样你可以从你的代码中引用它,并在它交换标签。
一旦你确定了片段出现在布局上,基本步骤添加的标签是:
实施ActionBar.TabListener接口。该接口提供回调选项卡上的事件,当用户按下一个,这样你可以换标签等。
对于要添加的每个选项卡,实例化一个ActionBar.Tab并通过调用setTabListener设置ActionBar.TabListener()。还设置选项卡的标题和的setText()(以及可选的setIcon用一个图标())。
然后通过调用addTab添加每个选项卡来操作栏()。
注意,ActionBar.TabListener回调方法不指定该片段与所述标签相关联的,而仅仅是其中ActionBar.Tab被选中。你必须定义每个ActionBar.Tab,它代表了相应片段之间你自己的关联。有几种方法可以定义的关联,这取决于你的设计。
例如,这里是你如何实现的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.
}
}
标签
@Override 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 = getSupportActionBar(); 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); }如果你的活动停止后,您应保留与保存的实例状态当前选择的选项卡,因此您可以在用户返回打开相应的选项卡。当它的时间来保存状态,您可以查询与setSelectedNavigationIndex当前选定的选项卡()。这将返回选定的选项卡的索引位置。
actionBar.setListNavigationCallbacks(mSpinnerAdapter, mNavigationCallback);此方法需要您SpinnerAdapter和ActionBar.OnNavigationListener。
<SomeView ... android:layout_marginTop="?android:attr/actionBarSize" />您也可以在运行时使用的getHeight检索操作栏高度()。这反映了当时的操作栏,它被称为,这可能不包括堆叠操作栏(由于导航选项卡)如果在早期活动的生命周期方法调用的高度。就看你如何确定在运行时的总高度,包括堆叠操作栏,看到蜂窝库示例应用程序的标题片段类。
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- the theme applied to the application or activity --> <style name="CustomActionBarTheme" parent="@style/Theme.AppCompat.Light"> <item name="android:actionBarStyle">@style/MyActionBar</item> <item name="android:actionBarTabTextStyle">@style/TabTextStyle</item> <item name="android:actionMenuTextColor">@color/actionbar_text</item> <!-- Support library compatibility --> <item name="actionBarStyle">@style/MyActionBar</item> <item name="actionBarTabTextStyle">@style/TabTextStyle</item> <item name="actionMenuTextColor">@color/actionbar_text</item> </style> <!-- general styles for the action bar --> <style name="MyActionBar" parent="@style/Widget.AppCompat.ActionBar"> <item name="android:titleTextStyle">@style/TitleTextStyle</item> <item name="android:background">@drawable/actionbar_background</item> <item name="android:backgroundStacked">@drawable/actionbar_background</item> <item name="android:backgroundSplit">@drawable/actionbar_background</item> <!-- Support library compatibility --> <item name="titleTextStyle">@style/TitleTextStyle</item> <item name="background">@drawable/actionbar_background</item> <item name="backgroundStacked">@drawable/actionbar_background</item> <item name="backgroundSplit">@drawable/actionbar_background</item> </style> <!-- action bar title text --> <style name="TitleTextStyle" parent="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"> <item name="android:textColor">@color/actionbar_text</item> </style> <!-- action bar tab text --> <style name="TabTextStyle" parent="@style/Widget.AppCompat.ActionBar.TabText"> <item name="android:textColor">@color/actionbar_text</item> </style> </resources>在您的清单文件,您可以应用主题,您的整个应用程序:
<application android:theme="@style/CustomActionBarTheme" ... />或个别活动:
<activity android:theme="@style/CustomActionBarTheme" ... />注意:一定每个主题和风格声明在<style>标签,从它继承你的主题没有明确宣布所有样式父主题。当修改操作栏,使用父主题,这样你可以简单地覆盖你想改变,而无需重新实现你想独自离开(如文本大小或行动项目填充)样式的操作栏的样式是很重要的。