一、ActionBar 简介
1. ActionBar定义:
如下图所示即为一个ActionBar,其最基本的形式,就是为 Activity 显示标题,并且在标题左边显示一个 app icon
注:设置一个基本的 ActionBar,需要 app 使用一个 activity 主题,该主题必须是 ActionBar可用的
注:
<1> ActionBar的图标,可显示软件图标,也可用其他图标代替。当软件不在最高级页面时,图标左侧会显示一个左箭头,用户可以通过这个箭头向上导航;
<2> 如果你的应用要在不同的View中显示数据,这部分允许用户来切换视图。一般的作法是用一个下拉菜单或者是Tab选项卡。如果只有一个界面,那这里可以显示应用程序的标题或者是更长一点的商标信息;
<3> 两个action按钮,这里放重要的按钮功能,为用户进行某项操作提供直接的访问;
<4> overflow按钮,放不下的按钮会被置于“更多...”菜单项中,“更多...”菜单项是以下拉形式实现的
2. ActionBar的功能:
一个专门的空间用来显示你的app的标识,以及指出目前所处在app的哪个页面
以一种可预见的方式访问重要的操作(比如搜索)
支持导航和视图切换(通过Tabs和下拉列表)
二、ActionBar应用
1. 添加ActionBar
ActionBar的添加非常简单,只需要在AndroidManifest.xml中指定Application或Activity的theme是Theme.Holo或其子类就可以了,在Android 3.0及更高的版本中,Activity中都默认包含有ActionBar组件。
<application android:theme="@android:style/Theme.Holo.Light.DarkActionBar" >
2. 取消ActionBar
有两种方法可以取消ActionBar
方法一:在manifest文件中设置activity的theme属性为Theme.NoTitleBar
<activity android:theme="@android:style/Theme.NoTitleBar">
方法二:在运行时调用hide()方法隐藏ActionBar,然后可以在需要的时候调用show()方法来显示ActionBar()
ActionBar actionBar = getActionBar(); actionBar.hide();
3. 自定义ActionBar
默认情况下,系统会使用<application>或者<activity>中icon属性指定的图片来作为ActionBar的图标,但是我们也可以改变这一默认行为。如果我们想要使用另外一张图片来作为ActionBar的图标,可以在<application>或者<activity>中通过logo属性来进行指定,而标题中的内容使用label属性来指定。如:
<application android:icon="@drawable/bottle" android:label="Hello" android:theme="@android:style/Theme.Holo.Light.DarkActionBar" >
效果如下:
三、添加Action Buttons
所有的操作按钮和 action overflow 中其他可用的条目都被定义在 menu资源 的 XML 文件中。通过在项目的res/menu 目录中新增一个 XML 文件来为 action bar 添加操作。为想要添加到 action bar 中的每个条目添加一个 <item> 元素。 如我在res/menu下新建了一个名为menu_action_bar的文件,文件内容为:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/action_bar_alarm" android:icon="@drawable/ic_alarm_on_grey" android:showAsAction="always" android:title="@string/action_alarm"/> <item android:id="@+id/action_bar_favorite" android:icon="@drawable/ic_favorite_grey" android:showAsAction="ifRoom" android:title="@string/action_favorite"/> <item android:id="@+id/action_bar_help" android:icon="@drawable/ic_help_grey" android:showAsAction="withText" android:title="@string/action_help"/> <item android:id="@+id/action_bar_settings" android:icon="@drawable/ic_settings_grey" android:orderInCategory="100" android:showAsAction="never" android:title="@string/action_settings"/> </menu>
在上面的menu文件中定义了两个菜单按钮,第一个是一个闹钟,总是会显示在ActionBar上,另一个是一个点赞按钮,当ActionBar空间足够时,该按钮会显示在ActionBar上,而当空间不足时,该按钮则不会显示。<item>标签中属性含义:id是该Action按钮的唯一标识符,icon用于指定该按钮的图标,title用于指定该按钮可能显示的文字(在图标能显示的情况下,通常不会显示文字),actionViewClass用来指定一个构建视窗所使用的布局资源,showAsAction则指定了该按钮显示的位置,主要有以下几种值可选:
ifRoom | 会显示在Item中,但是如果已经有4个或者4个以上的Item时会隐藏在溢出列表中。当然个 |
数并不仅仅局限于4个,依据屏幕的宽窄而定 | |
never | 永远不会显示。只会在溢出列表中显示,而且只显示标题,所以在定义item的时候,最好 |
把标题都带上。 | |
always | 无论是否溢出,总会显示。 |
withText | withText值示意Action bar要显示文本标题。Action bar会尽可能的显示这个 |
标题,但是,如果图标有效并且受到Action bar空间的限制,文本标题有可 | |
能显示不全。 | |
collapseActionView | 声明了这个操作视窗应该被折叠到一个按钮中,当用户选择这个按钮时,这个操作视窗展开。否则, |
这个操作视窗在默认的情况下是可见的,并且即便在用于不适用的时候,也要占据操作栏的有效空间。 | |
一般要配合ifRoom一起使用才会有效果。 |
然后在Activity中重写onCreateOptionsMenu()方法,将menu文件中定义的item添加到指定Activity的ActionBar上:
@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu_action_bar, menu); return super.onCreateOptionsMenu(menu); }
效果如下:
可以看到,由于空间不足,所以后面三个buttons没有显示在ActionBar上,而是隐藏在overflow(即闹钟后面的三个点)里面了,点击overflow图标,后面的item项便会显示
注意:
1. 一般来说,显示在ActionBar上面的Button只会显示icon,而不会显示title;而voerflow中的项一般只显示title,而不显式icon;
2. 出于以下两方面考虑,我们应为每一个item设置title属性:
当ActionBar中的剩余空间不足的时候,如果Action按钮指定的showAsAction属性是ifRoom的话,该Action按钮就会出现在overflow当中,此时就只有title能够显示了
如果Action按钮在ActionBar中显示,用户可能通过长按该Action按钮的方式来查看到title的内容
总结:
在ActonBar上添加button主要有两个步骤:
1)在res/menu中定义一个菜单文件,文件中包含需要显示在ActionBar/overflow中的item;
2)在activity中重写onCreateOptionsMenu()方法,将menu文件中定义的item添加到指定Activity的ActionBar上;
四、为Action Buttons添加动作
在Activity中重写onMenuItemSelected方法
@Override public boolean onMenuItemSelected(int featureId, MenuItem item) { switch (item.getItemId()) { case R.id.action_bar_alarm: showToast("alarm"); startNextActivity(); return true; case R.id.action_bar_favorite: showToast("favorite"); return true; case R.id.action_bar_help: showToast("help"); return true; case R.id.action_bar_settings: showToast("settings"); return true; default: return super.onMenuItemSelected(featureId, item); } }
注:代码中的showToast是我自己写的一个私有方法
private void showToast(String str) { Toast.makeText(this, "You are choosing the action bar item " + str + " !", Toast.LENGTH_SHORT).show(); }
此时,点击某一个button,便会显示相应的toast消息。
五、为下级activity添加向上导航功能
可以在 ActionBar中为用户提供一个导航到逻辑父屏的up button(向上按钮),如下图所示,图标左边的箭头就是一个指向逻辑父屏的up button:
当运行在 Android 4.1(API level 16) 或更高版本,或者使用 Support 库中的 ActionBarActivity 时,实现向上导航需要在 manifest 文件中声明父 activity ,同时在 action bar 中设置向上按钮可用。
使用步骤:首先需要在manifest文件中通过android:parentActivityName=””指定该activity的父activity,然后在activity的onCreate方法中调用getAction().setDisplayHomeAsUpEnabled() 来把 app icon 设置成可用的向上按钮。
六、自定义ActionBar的风格
1. 使用一个 Android 主题
Android 包含三个基本的 activity 主题,这三个主题决定了 action bar 的颜色:
Theme.Holo :一个 “dark” 的主题
Theme.Holo.Light :一个 “light” 的主题
Theme.Holo.Light.DarkActionBar:action bar 为dark,其他部分为light
可以通过在 manifest 文件中设置 <application> 元素 或 <activity> 元素的 android:theme 属性,对整个应用程序或者单一的 activity 设置action bar的主题风格;
注:当使用 Support 库时,必须使用 Theme.AppCompat 主题替Theme.Holo
方法:为改变 ActionBar的背景,可以通过为 activity 创建一个自定义主题,并重写 actionBarStyle 属性来实现。actionBarStyle 属性指向另一个样式,在该样式里,通过指定一个 drawable 资源来重写 background 属性。如果我们的 app 使用了 navigation tabs 或 split action bar ,也可以通过分别设置 backgroundStacked 和 backgroundSplit 属性来为这些条指定背景。
注:为自定义主题和样式声明一个合适的父主题,这点很重要。如果没有父样式,ActionBar将会失去很多默认的样式属性,除非我们自己显式的对他们进行声明。
步骤:
1. 定义一个主题资源文件,如res/values/themes.xml,其中themes.xml即为ActionBar的主题;
2. 将主题应用到 app 全局或单个的 activity 之中;(具体使用见博客代码)
修改ActionBar中的文本颜色时,需要为ActionBar的title、action buttons和tabs分别设置文本颜色;
title:在 activity 主题中重写 actionBarStyle,为其指定一种自定义样式,并在该自定义样式中指定 textColor 属性
action buttons:在 activity 主题中重写 actionBarTabTextStyle
tabs:在 activity 主题中重写 actionMenuTextColor
4. 自定义 Tab Indicator
为 activity 创建一个自定义主题,通过重写 actionBarTabStyle 属性来改变 navigation tabs 使用的指示器。actionBarTabStyle 属性指向另一个样式资源;在该样式资源里,通过指定一个state-list drawable 来重写 background属性。
注:一个state-list drawable 是重要的,它可以通过不同的背景来指出当前选择的 tab 与其他 tab 的区别。
Why:通常情况下,action bar会位于布局文件的顶部,这将会占用布局文件的有效空间,当调用 ActionBar 的 hide()或show()实现action bar的隐藏/显示时,就会导致 activity 基于新尺寸重新计算与绘制布局。
为避免在ActionBar隐藏和显示过程中调整布局的大小,可以为ActionBar启用叠加模式(overlay mode)。在叠加模式下,ActionBar会叠加在布局之上,这样虽然会遮挡部分布局文件,但当 ActionBar隐藏或显示时,系统不再需要调整布局。(如下图所示,该图中ActionBar为透明背景和叠加模式,通过自定义ActionBar的背景为透明,可以使得布局文件依旧可见)
How:自定义一个主题,该主题继承于已经存在的 ActionBar主题,并设置 android:windowActionBarOverlay 属性的值为 true
<resources> <!-- 为程序或者活动应用的主题样式 --> <style name="CustomActionBarTheme" parent="@android:style/Theme.AppCompat"> <item name="android:windowActionBarOverlay">true</item> <!-- 兼容支持库 --> <item name="windowActionBarOverlay">true</item> </style> </resources>
注:该主题包含两种不同的 windowActionBarOverlay 式样定义:一个带 android: 前缀,另一个不带。带前缀的适用于包含该式样的 Android 系统版本,不带前缀的适用于通过从 Support 库中读取式样的旧版本
当使用层叠模式时,ActionBar会遮挡部分布局,为了避免布局文件被遮挡,可以在布局文件的根控件中设置android:paddingTop="?android:attr/actionBarSize"或android:margingTop="?android:attr/actionBarSize",使得布局文件始终位于ActionBar下方
注:如果在 ActionBar中使用 Support 库,需要将"?android:attr/actionBarSize"替换成"? attr/actionBarSize",不带前缀的 ?attr/actionBarSize 适用于包括Android 3.0 和更高的所有版本