简介
action bar 是一个功能窗口,用于标识应用程序和用户的位置,
并提供给用户一些操作和导航模式。你应该在大多数需要提供用户操作或导航的
activities
时使用它。
因为action bar 为用户在不同的屏幕上
提供了
一致的界面,并且它优雅的适应类不同的系统外观。你可以通过使用
ActionBar
类来控制action bar 。
Action Bar 的主要目标:
- 提供一个专有的空间用于显示应用程序的标识或用户的位置
- 在不同的application上提供一致的导航和细化视图
- 突出显示一些关键的活动(例如查找、分享),并且能够实现它们的功能
从左到又依次为:logo(1)、导航选项卡(2)、任务项目(3)
添加action bar
从安卓3.0(V11)开始,action bar就已经包含在了
Theme.Holo
这类主题之中。该主题为
targetSdkVersion="11"或之上的默认主题
如果你想使用action bar 的API,例如增加导航模式或者自定义样式,应该设置
android:minSdkVersion
=
"11"或之上。
移除action bar
如果你在一个activity中不需要 action bar 设置它的主题为. NoActionBar,或者调用action bar的hide()方法进行隐藏,当然,show()方法可以再显示出来。
注意由于action bar的移除或隐藏而带来的布局空间的变化。如果你的activity经常性的进行action bar的隐藏/显示,你或许应该使用叠加模式(
overlay mode
)进行布局。
将你的action bar 放在最上层布局中,这样action bar的显隐便不会影响你的布局。
使用叠加模式,为你的activity创建一个主题且设置
android:windowActionBarOverlay=true,更多信息请查看。
添加action items(活动项)
有时候你需要在选项菜单中给用户一些直接的选项,为了实现它,必须在action bar中声明这些菜单项(menu item)并作为活动项。
一个活动项包含一个icon和text title,如果一个菜单项没有作为活动项显示,那么系统会将它放在溢出菜单(overflow menu)中。
当activitty第一次启动,系统通过调用
onCreateOptionsMenu()填充action bar 和溢出菜单。
在这个回调方法中,你应该增加一个XML文件用以定义菜单项的菜单资源。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_activity, menu);
return true;
}
在这个xml文件中,你可以设置一个菜单项作为活动项通过
<item>元素中的
声明:
android:showAsAction="ifRoom" 这样,只有当有足够空间时才会直接显示在action bar上,否则会被收入溢出菜单。
设置显示的图标和文字:
android:title
、
android:icon 但安卓只会默认的显示icon。如果需要显示文字,必须在
android:showAsAction中加上
withText。可能由于空间问题文字显示不全。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_save"
android:icon="@drawable/ic_menu_save"
android:title="@string/menu_save"
android:showAsAction="ifRoom|withText" />
</menu>
当用户选中了某一个活动项,activity recive便会调用 onOptionsItemSelected()。
为每个菜单项定义他的title是十分有必要的,尽管他不会总是显示出来:
- 当没有足够空间显示该活动项时,它便会收入溢出菜单,而在溢出菜单中显示的是它的title
- 有时屏幕受损的用户需要阅读title而不是icon
- 如果活动项仅仅显示icon,用户可以长按按钮来显示这个item的title
icon项是可选的,但也是推荐有的。
如果你在fragement中添加菜单项,要确保 onOptionsItemSelected()
先于fragement内的回调函数。
你也可以声明一个项目总是(always)作为活动项显示,而不是收入溢出菜单。当空间受限时,就不该使用always这个值。最好使用ifRoom。
选则活动项
你应该谨慎的选择那些直接显示出来的菜单项作为活动项,一般,每一个活动项至少遵循一种如下情况:
- 频繁使用:十次有七次都会使用的操作
- 重要:它提供的功能能够简便用户的操作。
- 典型的:在类似的app中都会提供的操作,例如刷新,新建等。
如果你有超过4个菜单项需要作为活动项,那么你必须谨慎的考虑他们的相对等级,并且努力不要超过4个活动项(使用ifRoom是个好办法),即使有足够的空间也不应该显示太多的活动项。
另外,如下的操作都不应该作为活动项显示:设置、帮助、反馈或者类似的。
如果有需要,查找操作应该是你显示的第一个活动项
使用分离操作栏(split action bar)
这是一个专门为狭窄屏幕手机设计的action bar,它的导航部分(2)和app声明部分(1)是分离的。
使用它必须在manifest文件中的<application>或<activity>中加上
uiOptions="splitActionBarWhenNarrow"。
尽管在4.0才出现的,但在之前的版本也能工作
使用app 图标进行导航
默认情况下,你的app图标会显示在action bar的左边,如果需要,可以将它作为一个活动项。一般会做如下两件事情:
- 回到应用的主activity
-
Navigating up
当用户触摸icon 系统便会调用activity里的
onOptionsItemSelected()
方法,并且传递
android.R.id.home
ID。作为响应,应该启动主actiivty或者返回上一个activity。
如果是返回主activity,应该在intent中设置flag=
FLAG_ACTIVITY_CLEAR_TOP有了这个flag,它会销毁在主activity之前的所有activity,以确保主activity在第一个(栈顶)。
下面是一个点击icon返回主activity的片段
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// app icon in action bar clicked; go home
Intent intent = new Intent(this, HomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
为确保用户能够通过其它app进入当前的activity,也可能需要加上
FLAG_ACTIVITY_NEW_TASK
flag。事实上,当你的app需要接受来自其他app的intent,都需要加入该flag。
在4.0及其之后的版本,你必须调用
setHomeButtonEnabled(true)
指定icon作为一个活动项。
Navigating up
up 不同于back ,有时候会另启一个新的任务栈,从而不能使用返回键返回上一屏幕状态。
使用该功能,必须调用action bar的
setDisplayHomeAsUpEnabled(true)
函数,其它设置同上。
使用action view
action view 是作为action item按钮的替代项而显示在action bar上的小部件。
在你的菜单资源文件中
声明一个action view
需含有
android:actionLayout
或者
android:actionViewClass
属性
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_search"
android:title="@string/menu_search"
android:icon="@drawable/ic_menu_search"
android:showAsAction="ifRoom|collapseActionView"//表明需要嵌入一个button中,当用户点击该按钮,view展开。
android:actionViewClass="android.widget.SearchView" />
</menu>
如果需要添加一些事件钩子,可以在 onCreateOptionsMenu()中通过如下示例获得实例对象:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.options, menu);
SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
// Configure the search info and add any event listeners
...
return super.onCreateOptionsMenu(menu);
}
action view 的折叠处理
一般系统会自动处理扩展和折叠,你不必做任何操作,只需要像上面item这样配置即可。
一般对查找功能的action view的操作,建议使用
SearchView
. 这个类。当然,一些设备也会提供专有的查找按钮,使用时只需在
onKeyUp()
监听
KEYCODE_SEARCH
事件,然后调用
expandActionView()
.
你可以在展开或折叠后做一些事情,通过设置监听器:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.options, menu);
MenuItem menuItem = menu.findItem(R.id.actionItem);
...
menuItem.setOnActionExpandListener(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
}
});
}
使用action provider
详情请跳转至 Action Provider
使用导航选项卡(Navigation Tabs)
在选项卡之间切换的本质是使用
FragmentTransaction
,
切换fragement,如果不熟悉fragement的切换,请看延伸阅读关于fragemnt部分。
使用一个view group包含每一个fragement的tab,并确保view group有一个id以便于在你的切换代码中引用它。
一旦你决定类如何显示你的fragement,将它加入tab需要如下基本几步:
- Implement
ActionBar.TabListener
- 对于每个你想加入的tab 实例化一个
ActionBar.Tab
and 通过调用setTabListener()设置
ActionBar.TabListener
. 也还要设置tab的title/icon 通过 setText()
/ setIcon()
.
- 通过调用
addTab()
.将每一个tab加入action bar。
关于tabListener,下面一段示例展示了一个标准的fragement转换规则:
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.
}
}
这个片段展示类如何显示tab,它使用了上面的Listener:
@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 = 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);
}
如果你的app停止运行了,你必须保存现有的选择状态。调用
getSelectedNavigationIndex()获得当前选中的选项卡的index。
使用下拉的导航(
drop-down Navigation )
基本步骤如下:
- 创建一个
SpinnerAdapter
用于提供下拉的选项和布局
- Implement
ActionBar.OnNavigationListener
- 为action bar 启用导航模式:actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
- 设置回调:actionBar.setListNavigationCallbacks(mSpinnerAdapter, mNavigationCallback);
下面几段代码展示了简单的使用:
步骤1:
SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this, R.array.action_list,
android.R.layout.simple_spinner_dropdown_item);
<?xml version="1.0" encoding="utf-8"?>
<!---数组文件--->
<resources>
<string-array name="action_list">
<item>Mercury</item>
<item>Venus</item>
<item>Earth</item>
</string-array>
</pre>
步骤2:
mOnNavigationListener = new OnNavigationListener() {
// Get the same strings provided for the drop-down's ArrayAdapter
String[] strings = getResources().getStringArray(R.array.action_list);
@Override
public boolean onNavigationItemSelected(int position, long itemId) {
// Create new fragment from our own Fragment class
ListContentFragment newFragment = new ListContentFragment();
FragmentTransaction ft = openFragmentTransaction();
// Replace whatever is in the fragment container with this fragment
// and give the fragment a tag name equal to the string at the position selected
ft.replace(R.id.fragment_container, newFragment, strings[position]);
// Apply changes
ft.commit();
return true;
}
};
action bar的样式
如果你想在你的应用中使用自定义小部件,那么也应该重新设计action bar使之匹配你的风格设计。为此,你需要使用安卓的样式和主题框架。
选择图片匹配不同状态下的控件(例如按钮的按下、弹起、选择),使用xml文件的selector。
你提供所有背景图片,使用.9png格式具有更好的延展性。.9png格式的图片高不超过40px宽不超过30px
普通外观
android:windowActionBarOverlay
声明action bar是覆盖整个activity layout 而不是根据layout进行偏移,(例如 画廊应用
Gallery app
就是使用此样式)它的默认值是false。
通常,action bar需要自己的空间,然后你的布局再填充剩下的空间。当使用 覆盖模式(overlay mode)时,布局会使用所有可用的空间,然后action bar 绘制在屏幕的顶部。
当你的内容大小和位置是固定的时候,覆盖模式实现action bar的显示/隐藏时会有很好的效果。
也可以使用一个半透明的背景,这样在action bar的下面仍然可以看到一些内容。
注意:Hole主题会默认的半透明的绘制action bar,你可以用自定义的样式来修改它。在
DeviceDefault
主题下默认的绘制是不透明的。
当覆盖模式启用时,你的layout并不会意识到有action bat在顶部。因此,必须注意在action bar覆盖的部分不能放置重要信息或者ui组件。如果合适的话,可以引用平台的 actionBarSize确定action bar的高度。在xml布局文件中引用这个值
<SomeView
...
android:layout_marginTop="?android:attr/actionBarSize" />
还可以使用
getHeight()
.获得action bar的高度,如果在activity生命周期的早期调用这个方法,那么调用时返回的高度并不包括堆叠操作栏(因为导航标签)。
要看如何在运行时判断操作栏总的高度(包括被堆放的操作栏),请看 Honeycomb Gallery
示例应用中的 TitlesFragment
类。
action items
android:actionButtonStyle
为按钮定义一个样式资源
android:actionBarItemBackground
为每个action item定义一个背景资源 (Added in API level 14.)
android:itemBackground
为每个 溢出菜单中的item定义背景资源
android:actionBarDivider
在action item之间(即分割线)指定图片资源 (Added in API level 14.)
android:actionMenuTextColor
action item显示文本的颜色
android:actionMenuTextAppearance
action item显示文本的样式
android:actionBarWidgetTheme
给作为操作视窗被填充到操作栏中的可视构件定义主题资源(Added in API level 14.)
Navigation tabs
android:actionBarTabStyle
给操作栏中的选项标签定义样式资源。
android:actionBarTabBarStyle
给显示在导航选项标签下方的细条定义样式资源。
android:actionBarTabTextStyle
给导航选项标签中的文本定义样式资源。
Drop-down lists
android:actionDropDownStyle
给下拉列表定义样式资源。
下面的片段展示了给一个action bar 定义的一些样式
<?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>
标签都必须有一个父主题。这样当一些样式你没有指定的时候会使用父主题的样式。
在整个应用或activitys中使用你的样式:
<application
android:theme
=
"@style/CustomActivityTheme"
...
/>
高级样式
如果需要使用比上述更高级的样式,在你的主题中包含
android:actionBarStyle
and
android:actionBarSplitStyle
可以定义action bar的各种属性,包括
android:background
,
android:backgroundSplit
, and
android:backgroundStacked
. 的不同背景。同样,确保有个父主题。
下面是一个示例改变操作栏背景
<?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>
延伸阅读
了解更多关于上下文操作栏的信息: http://android-doc.com/guide/topics/ui/menus.html#context-menu
action bar 设计指导 http://android-doc.com/design/patterns/actionbar.html
关于flag和app的返回行为: http://android-doc.com/guide/components/tasks-and-back-stack.html
关于Search 接口/查找功能的实现: http://android-doc.com/guide/topics/search/search-dialog.html
关于fragement: http://android-doc.com/guide/components/fragments.html
关于安卓的样式和主题: http://android-doc.com/guide/topics/ui/themes.html
Honeycomb Gallery
示例 http://android-doc.com/resources/samples/HoneycombGallery/index.html
别人对于action bar的理解 http://blog.csdn.net/xyz_lmn/article/details/8132420#t16