一、概念
在Android 3.0中,ActionBar是一个非常重要的交互元素,ActionBar取代了传统的标题栏,在程序运行中一直置于顶部,对于Android平板设备来说,屏幕更大,标题栏使用ActionBar来设计可以展示更多丰富的内容,方便操控。
二、使用
1.添加ActionBar
在Android 3.0及更高的版本中,Activity中都默认包含有ActionBar。
2.取消ActionBar
manifest设置:
代码设置:
ActionBar actionBar = getActionBar();
actionBar.hide(); //隐藏
actionBar.show(); //显示
如果使用一个主题(theme)来移除Activity上的ActionBar,那么窗口将不再会有ActionBar,因此在运行时也就没有办法来添加ActionBar,调用getActionBar()方法会返回null值。
3.添加Action按钮
ActionBar可以根据应用程序当前的功能来提供与其相关的Action按钮,这些按钮都会以图标或文字的形式直接显示在ActionBar上。当然,如果按钮过多,ActionBar上显示不完,多出的一些按钮可以隐藏在overflow里面(最右边的三个点就是overflow按钮),点击一下overflow按钮就可以看到全部的Action按钮了。
(1)定义menu资源
//menu_main.xml
这里我们通过
id:是该Action按钮的唯一标识符;
icon:用于指定该按钮的图标;
title:用于指定该按钮可能显示的文字(在图标能显示的情况下,通常不会显示文字);
actionViewClass:用于指定一个构建视窗所使用的布局资源;
showAsAction:用于指定按钮显示的位置。
showAsAction主要有以下几种值可选:
ifRoom:会显示在Item中,但是如果已经有4个或者4个以上的Item时会隐藏在溢出列表中,当然个数并不仅仅局限于4个,依据屏幕的宽窄而定。
never:永远不会显示,只会在溢出列表中显示,而且只显示标题,所以在定义item的时候,最好把标题都带上。
always:无论是否溢出,总会显示。
withText:示意ActionBar要显示文本标题,ActionBar会尽可能显示这个标题,但是如果图标有效并且受到ActionBar空间的限制,文本标题有可能显示不全。
collapseActionView:声明了这个操作视窗应该被折叠到一个按钮中,当用户选择这个按钮时,这个操作视窗展开,否则这个操作视窗在默认的情况下是可见的,并且即便在用于不适用的时候,也要占据操作栏的有效空间,一般要配合ifRoom一起使用才会有效果。
title中的内容通常情况下只会在overflow中显示出来,ActionBar中由于屏幕空间有限,默认是不会显示title内容的。但是出于以下几种因素考虑,即使title中的内容无法显示出来,我们也应该给每个item中都指定一个title属性:
●当ActionBar中的剩余空间不足的时候,如果Action按钮指定的showAsAction属性是ifRoom的话,该Action按钮就会出现在overflow当中,此时就只有title能够显示了。
●如果Action按钮在ActionBar中显示,用户可能通过长按该Action按钮的方式来查看到title的内容。
(2)重写Activity的onCreateOptionsMenu()方法
当Activity启动的时候,系统会调用Activity的onCreateOptionsMenu()方法来取出所有的Action按钮,我们只需要在这个方法中去加载一个menu资源,并把所有的Action按钮都定义在资源文件里面就可以了。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
return super.onCreateOptionsMenu(menu);
}
(3)重写Activity的onOptionsItemSelected()方法
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.user_p:
Toast.makeText(this, "你点击了“用户”按键!", Toast.LENGTH_SHORT).show();
return true;
case R.id.write_p:
Toast.makeText(this, "你点击了“发布”按键!", Toast.LENGTH_SHORT).show();
return true;
case R.id.favo_p:
Toast.makeText(this, "你点击了“收藏”按键!", Toast.LENGTH_SHORT).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
4.通过ActionBar图标进行导航
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
...
}
}
5.添加ActionView
ActionView是一种可以在ActionBar中替换Action按钮的控件,它可以允许用户在不切换界面的情况下通过ActionBar完成一些较为丰富的操作。比如说,你需要完成一个搜索功能,就可以将SeachView这个控件添加到ActionBar中。
(1)定义menu资源
为了声明一个ActionView,我们可以在menu资源中通过actionViewClass属性来指定一个控件:
(2)重写Activity的onCreateOptionsMenu()方法
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchItem.getActionView();
// 配置SearchView的属性
...
return super.onCreateOptionsMenu(menu);
}
有些程序可能还希望在ActionView展开和合并的时候显示不同的界面,其实我们只需要去注册一个ActionView的监听器就能实现这样的功能:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
searchItem.setOnActionExpandListener(new OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
Log.d("TAG", "on expand");
return true;
}
@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
Log.d("TAG", "on collapse");
return true;
}
});
return super.onCreateOptionsMenu(menu);
}
6.添加ActionProvider
和ActionView有点类似,ActionProvider也可以将一个Action按钮替换成一个自定义的布局。但不同的是,ActionProvider能够完全控制事件的所有行为,并且还可以在点击的时候显示子菜单。
(1)定义menu资源
为了添加一个ActionProvider,我们需要在
(2)重写Activity的onCreateOptionsMenu()方法
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
MenuItem shareItem = menu.findItem(R.id.action_share);
ShareActionProvider provider = (ShareActionProvider) shareItem
.getActionProvider();
provider.setShareIntent(getDefaultIntent());
return super.onCreateOptionsMenu(menu);
}
private Intent getDefaultIntent() {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/*");
return intent;
}
这里我们通过getDefaultIntent()方法来构建了一个Intent,该Intent会将所有可以共享图片的程序都列出来。
这个ShareActionProvider点击之后是可以展开的,有点类似于overflow的效果,这就是ActionProvider的子菜单。
7.添加导航Tabs
Tabs的应用可以算是非常广泛了,它可以使得用户非常轻松地在应用程序中切换不同的视图。而Android官方更加推荐使用ActionBar中提供的Tabs功能,因为它更加的智能,可以自动适配各种屏幕的大小。比如说,在平板上屏幕的空间非常充足,Tabs会和Action按钮在同一行显示,而如果是在手机上,屏幕的空间不够大的话,Tabs和Action按钮则会分为两行显示。
添加步骤:
(1)实现ActionBar.TabListener接口,这个接口提供了Tab事件的各种回调,比如当用户点击了一个Tab时,可以进行切换Tab的操作;
(2)为每一个想添加的Tab创建一个ActionBar.Tab的实例,并且调用setTabListener()方法来设置ActionBar.TabListener。除此之外,还需要调用setText()方法来给当前Tab设置标题;
(3)最后调用ActionBar的addTab()方法将创建好的Tab添加到ActionBar中。
//TabListener
import android.app.ActionBar;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
public class TabListener implements ActionBar.TabListener {
private Fragment mFragment;
private final Activity mActivity;
private final String mTag;
private final Class 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 clz) {
mActivity = activity;
mTag = tag;
mClass = clz;
}
/* The following are each of the ActionBar.TabListener callbacks */
public void onTabSelected(ActionBar.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(ActionBar.Tab tab, FragmentTransaction ft) {
if (mFragment != null) {
// Detach the fragment, because another one is being attached
ft.detach(mFragment);
}
}
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
// User selected the already selected tab. Usually do nothing.
}
}
//Fragment1,Fragment2、Fragment3类似
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Fragment1 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment1, container, false);
}
}
//fragment1.xml,fragment2.xml、fragment3.xml类似
//MainActivity
private void initView() {
// 提示getActionBar方法一定在setContentView后面
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// 添加Tab选项
ActionBar.Tab tab = actionBar
.newTab()
.setText("澳门风云2")
.setTabListener(
new TabListener(this, "film1",
Fragment1.class));
actionBar.addTab(tab);
tab = actionBar
.newTab()
.setText("五十度灰")
.setTabListener(
new TabListener(this, "film2",
Fragment2.class));
actionBar.addTab(tab);
tab = actionBar
.newTab()
.setText("爸爸去哪儿2")
.setTabListener(
new TabListener(this, "film3",
Fragment3.class));
actionBar.addTab(tab);
}
8.添加下拉列表导航
作为Activity内部的另一种导航(或过滤)模式,操作栏提供了内置的下拉列表。下拉列表能够提供Activity中内容的不同排序模式。
添加步骤:
(1)创建一个给下拉提供可选项目的列表,以及描画列表项目时所使用的布局;
(2)实现ActionBar.OnNavigationListener回调,在这个回调中定义当用户选择列表中一个项目时所发生的行为;
(3)用setNavigationMode()方法该操作栏启用导航模式;
(4)用setListNavigationCallbacks()方法给下拉列表设置回调方法。
//strings.xml
- Fragment1
- Fragment2
- Fragment3
//MainActivity
private ActionBar.OnNavigationListener mOnNavigationListener;
private String[] arry_list;
private void initView() {
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
// //导航模式必须设为NAVIGATION_MODE_LIST
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
// 定义一个下拉列表数据适配器
SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this,
R.array.action_list,
android.R.layout.simple_spinner_dropdown_item);
arry_list = getResources().getStringArray(R.array.action_list);
mOnNavigationListener = new ActionBar.OnNavigationListener() {
@Override
public boolean onNavigationItemSelected(int position, long itemId) {
Fragment newFragment = null;
switch (position) {
case 0:
newFragment = new Fragment1();
break;
case 1:
newFragment = new Fragment2();
break;
case 2:
newFragment = new Fragment3();
break;
default:
break;
}
getFragmentManager()
.beginTransaction()
.replace(R.id.container, newFragment,
arry_list[position]).commit();
return true;
}
};
actionBar.setListNavigationCallbacks(mSpinnerAdapter,
mOnNavigationListener);
}
9.自定义ActionBar样式
(1)使用主题
可以将主题应用到整个应用程序,也可以只应用于某个Activity。通过在AndroidManifest.xml文件中给
android:theme="@android:style/Theme.Holo.Light.DarkActionBar"
(2)自定义背景
如果想要修改ActionBar的背景,我们可以通过创建一个自定义主题并重写actionBarStyle属性来实现。这个属性可以指向另外一个样式,然后我们在这个样式中重写background这个属性就可以指定一个drawable资源或颜色,从而实现自定义背景的功能。
(3)自定义文字颜色
(4)自定义Tab Indicator
为了可以明确分辨出我们当前选中的是哪一个Tab项,通常情况下都会在选中Tab的下面加上一条横线作为标识,这被称作Tab Indicator。如果要自定义Tab Indicator,首先我们需要重写actionBarTabStyle这个属性,将它指向一个新建的Tab样式,然后重写background这个属性即可。需要注意的是,background必须要指定一个state-list drawable文件,这样在各种不同状态下才能显示出不同的效果。
步骤1:准备四张图片,分别用于表示Tab的四种状态:选中未按下、选中且按下、未选中未按下、未选中且按下,并创建state-list drawable文件。
//actionbar_tab_indicator.xml
步骤2:修改style.xml文件。