本文介绍Android ActionBar的使用
最近在Android Studio中新建项目时发现Activity还是和以前一样,默认继承自ActionBarActivity,但是ActionBarActivity 却被标示为已经过时的API!对于这个问题,StackOverflow上已经有人回答了,请看ActionBarActivity deprecated,然后你会发现自从Android的兼容支持库升级到21版本以后(appcompat-v7-r21.1.0),ActionBarActivity 被 AppCompatActivity 取代了!还有一个变化是建议使用Toolbar,而不要使用原来的ActionBar 了!所以,这两节的内容我打算总结下ActionBar和Toolbar的基本使用,因为Toolbar实际上是ActionBar的扩展,所以这一节还是介绍复杂的ActionBar,下一节再继续介绍Toolbar。
1.ActionBar的来源
ActionBar是从Android 3.0开始引入的,它是用于取代3.0之前的标题栏,并提供更为丰富的导航效果。
2.添加ActionBar
(1)支持Android 3.0以上版本(API level 11)
如果要支持Android 3.0以上版本(API level 11),即android:minSdkVersion="11",那么很简单,只要Activity的Theme是使用了Theme.Holo 系列主题其中一种或者继承自这些主题,那么Activity就默认包含了ActionBar。
(2)支持Android 2.1以上版本(API level 7)
如果要支持Android 2.1以上版本(API level 7),即android:minSdkVersion="7",那么就要使用兼容支持库v7 appcompat。导入AppCompat支持库之后,只要Activity的Theme是使用了Theme.AppCompat 兼容主题其中一种或者继承自这些兼容主题,然后让Activity继承自appcompat中的ActionBarActivity 类即可。
3.设置ActionBar的风格
下图是三种不同的来自Theme.holo 系列的ActionBar的样式,对应于Theme.AppCompat 系列分别是Theme.AppCompat 、Theme.AppCompat.Light 、Theme.AppCompat.Light.DarkActionBar。
那么如何自定义呢?比如修改ActionBar的背景颜色该怎么办呢?和以前一样,我们可以继承默认的主题,然后修改默认主题中的某些样式来实现。
以修改ActionBar的背景颜色为例,如果是支持Android 3.0及以上版本的话可以用下面的方式,需要注意两点:(1)自定义android:actionBarStyle ;(2) 自定义的actionBarStyle 也要继承自某个actionBarStyle 样式。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- the theme applied to the application or activity -->
<style name="CustomActionBarTheme"
parent="@android:style/Theme.Holo.Light.DarkActionBar">
<item name="android:actionBarStyle">@style/MyActionBar</item>
</style>
<!-- ActionBar styles -->
<style name="MyActionBar"
parent="@android:style/Widget.Holo.Light.ActionBar.Solid.Inverse">
<item name="android:background">@drawable/actionbar_background</item>
</style>
</resources>如果是支持Android 2.1版本以上的话,可以用下面的方式,注意这里需要设置background和android:background两个属性的值:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- the theme applied to the application or activity -->
<style name="CustomActionBarTheme"
parent="@style/Theme.AppCompat.Light.DarkActionBar">
<item name="android:actionBarStyle">@style/MyActionBar</item>
<!-- Support library compatibility -->
<item name="actionBarStyle">@style/MyActionBar</item>
</style>
<!-- ActionBar styles -->
<style name="MyActionBar"
parent="@style/Widget.AppCompat.Light.ActionBar.Solid.Inverse">
<item name="android:background">@drawable/actionbar_background</item>
<!-- Support library compatibility -->
<item name="background">@drawable/actionbar_background</item>
</style>
</resources>类似的,我们还可以修改其他的样式,例如文本颜色等等。
如果我们想让ActionBar如下图所示悬浮起来的话,可以修改android:windowActionBarOverlay 样式为true。
//**For Android 3.0 and higher only**
<resources>
<!-- the theme applied to the application or activity -->
<style name="CustomActionBarTheme"
parent="@android:style/Theme.Holo">
<item name="android:windowActionBarOverlay">true</item>
</style>
</resources>
//**For Android 2.1 and higher**
<resources>
<!-- the theme applied to the application or activity -->
<style name="CustomActionBarTheme"
parent="@android:style/Theme.AppCompat">
<item name="android:windowActionBarOverlay">true</item>
<!-- Support library compatibility -->
<item name="windowActionBarOverlay">true</item>
</style>
</resources>在悬浮状态下,如果你又希望你的组件是一直处在ActionBar下面一直可见的,可以设置它的padding 或者 margin属性,值为actionBarSize。
//
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?android:attr/actionBarSize">
...
</RelativeLayout>
//
<!-- Support library compatibility -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize">
...
</RelativeLayout>
//In this case, the ?attr/actionBarSize value without the prefix works on all versions, including Android 3.0 and higher.4.添加Action Buttons
(4.1) 定义Action Buttons其实就是定义Menu,可以在/res/menu 新建菜单文件即可,如下所示:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- Search, should appear as action button -->
<item android:id="@+id/action_search"
android:icon="@drawable/ic_action_search"
android:title="@string/action_search"
android:showAsAction="ifRoom" />
<!-- Settings, should always be in the overflow -->
<item android:id="@+id/action_settings"
android:title="@string/action_settings"
android:showAsAction="never" />
</menu>当菜单项过多时,Android会分两种情况进行处理: 1、手机有MENU实体键:则按下Menu键后会显示剩余菜单项; 2、手机没有MENU实体键:则会在最左边显示一个Action OverFlow按钮,按下后会显示剩余项菜单。
属性 android:showAsAction 可以用来设置该菜单项的显示方式,共有5中属性值: never:永远不会显示。只会在溢出列表中显示。 ifRoom:会显示在Item中,但是如果已经有4个或者4个以上的Item时会隐藏在溢出列表中。 always:无论是否溢出,总会显示。 withText:Title会显示。 collapseActionView:可拓展的Item。
注意,如果你是为了兼容Android 2.1版本等低版本系统而使用了支持库Support Library 的话,你还需要自定义一个命名空间NameSpace,因为showAsAction 并不在android: 命名空间中,如下所示:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
<!-- Search, should appear as action button -->
<item android:id="@+id/action_search"
android:icon="@drawable/ic_action_search"
android:title="@string/action_search"
yourapp:showAsAction="ifRoom" />
...
</menu>(4.2) 然后在Activity的onCreateOptionsMenu中将Actions添加到ActionBar中
@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);
}(4.3) 点击Action之后的处理就是处理onOptionsItemSelected 方法
当用户选择一个Fragment的菜单项时,首先会调用Activity的onOptionsItemSelected()方法,如果该方法返回false,则调用Fragment实现的onOptionsItemSelected()方法。
@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_settings:
openSettings();
return true;
default:
return super.onOptionsItemSelected(item);
}
}(4.4) 如何利用ActionBar实现应用内的导航呢?
如果是在Anroid 4.1(API level 16)以上版本或者使用支持库中的ActionBarActivity的话,只需要在Manifest文件中指定Activity的父Activity即可,这样系统就知道返回的时候是回到哪个Activity了。(好在使用Android Studio的时候,每次新建Activity的时候都可以选择父Activity然后帮我们在Manifest文件中写好了)
如下所示,Android 4.1以上版本看android:parentActivityName 属性,以下版本看<meta-data> 元素:
<application ... >
...
<!-- The main/home activity (it 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 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.myfirstapp.MainActivity" />
</activity>
</application>然后在Activity中setDisplayHomeAsUpEnabled(true) 即可
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_displaymessage);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// If your minSdkVersion is 11 or higher, instead use:
// getActionBar().setDisplayHomeAsUpEnabled(true);
}如果细想的话,还要考虑当前Activity和父Activity所处的Stack的情况,那么就复杂了,可以参考Providing Up Navigation学习下如何处理不同的launchMode下的导航。
关于Android getActionBar vs getSupportActionBar?
这个一个经常出错的问题,可以看下这里Android getActionBar vs getSupportActionBar?,简言之,如果是支持Android 3.0以上版本(API level 11以上)使用getActionBar 即可,如果需要支持Android 2.1等低版本,那么肯定需要使用兼容支持库,那么就要使用其中的getSupportActionBar 才行。
其他的关于ActionBar的内容参见这篇文章Android UI开发详解之ActionBar,它还详细介绍了如果开发带Tab的ActionBar以及下拉模式的ActionBar等内容。
OK,ActionBar就介绍到这里,下面进入第二节——Toolbar。