Android ActionBar开发技巧

一. 什么是ActionBar,优点和缺点?

Action Bar是一种新増的导航栏功能,在Android 3.0之后加入到系统的API当中,它标识了用户当前操作界面的位置,并提供了额外的用户动作、界面导航等功能。使用ActionBar的好处是,它可以给提供一种全局统一的UI界面,使得用户在使用任何一款软件时都懂得该如何操作,并且ActionBar还可以自动适应各种不同大小的屏幕。目前在实际开发中,很多项目都会用到ActionBar,本篇文章参考http://blog.csdn.net/guolin_blog/article/details/18234477并增加了自己的内容,Thank you !

二. 如何使用ActionBar

1. 添加ActionBar

在AndroidManifest.xml中指定Application或Activity的theme是Theme.Holo或其子类

2. 删除ActionBar 

第一种方法:将theme指定成Theme.Holo.NoActionBar

第二种方法:调用以下代码去设置

ActionBar actionBar = getActionBar();
actionBar.hide();

3. 图标修改

在清单文件中指定Activity的login属性:android:logo="@drawable/ xxx

4. 标题修改  

在清单文件中指定Activity的label属性:android:label="xxx"

5. 添加Action按钮

当Activity启动的时候,系统会调用Activity的onCreateOptionsMenu()方法来取出所有的Action按钮

①.布局文件添加:在res/menu/xxx.xml中设置

<item
	android:id="@+id/action_compose"
	android:icon="@drawable/ic_action_compose"
	android:showAsAction="always"
	android:title="@string/action_compose"/>

②重写onCreateOptionsMenu方法

 
public boolean onCreateOptionsMenu(Menu menu) {
	MenuInflater inflater = getMenuInflater();
	inflater.inflate(R.menu.main, menu);
	return super.onCreateOptionsMenu(menu);
}

注意:当ActionBar中的剩余空间不足的时候,如果Action按钮指定的showAsAction属性是ifRoom的话,该Action按钮就会出现在overflow当中,此时就只有title能够显示了。如果Action按钮在ActionBar中显示,用户可能通过长按该Action按钮的方式来查看到title的内容。


6. 处理点击事件

重写onOptionsItemSelected方法 调用item.getItemId() 去处理

三. 如何使用ActionBar实现导航

ActionBar导航和Back键的区别:ActionBar中捕捉Home键调用finish方法,效果类似于Back键,但违背了最初的设计

三步设置ActionBar导航:
①. 调用setDisplayHomeAsUpEnabled(true),显示Home按钮
②. 在清单文件中配置父Activity

<meta-data
	android:name="android.support.PARENT_ACTIVITY"
	android:value="com.example.actionbartest.LaunchActivity" />

注:android4.1之后可以直接通过parentActivityName属性来指定
③. 捕捉Home按钮的点击事件进行处理
case android.R.id.home:
	Intent upIntent = NavUtils.getParentActivityIntent(this);
	if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
		TaskStackBuilder.create(this)
				.addNextIntentWithParentStack(upIntent)
				.startActivities();
		} else {
		upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
		NavUtils.navigateUpTo(this, upIntent);
	}
		return true;

四. 添加Action View

ActionView是一种可以在ActionBar中替换Action按钮的控件,它可以允许用户在不切换界面的情况下通过ActionBar完成一些较为丰富的操作,为了声明一个ActionView,我们可以在menu资源中通过actionViewClass属性来指定一个控件,例如可以使用如下方式添加SearchView:

<item
android:id="@+id/action_search"
android:icon="@drawable/ic_action_search"
android:actionViewClass="android.widget.SearchView"
android:showAsAction="ifRoom|collapseActionView"
android:title="@string/action_search" />
如果你还希望在代码中对SearchView的属性进行配置(比如添加监听事件等),完全没有问题,只需要在onCreateOptionsMenu()方法中获取该ActionView的实例就可以了,代码如下所示:

@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);
}
可以看到,调用MenuItem的setOnActionExpandListener()方法就可以注册一个监听器了,当SearchView展开的时候就会回调onMenuItemActionExpand()方法,当SearchView合并的时候就会调用onMenuItemActionCollapse()方法,我们在这两个方法中进行相应的UI操作就可以了。

五. Overflow按钮不显示

overflow按钮的显示情况和手机的硬件情况是有关系的,如果手机没有物理Menu键的话,overflow按钮就可以显示,如果有物理Menu键的话,overflow按钮就不会显示出来,在ViewConfiguration这个类中有一个叫做sHasPermanentMenuKey的静态变量,系统就是根据这个变量的值来判断手机有没有物理Menu键的。当然这是一个内部变量,我们无法直接访问它,但是可以通过反射的方式修改它的值,让它永远为false就可以了,代码如下所示:
@Override
protected void onCreate(Bundle savedInstanceState) {
	......
	setOverflowShowingAlways();
}

private void setOverflowShowingAlways() {
	try {
		ViewConfiguration config = ViewConfiguration.get(this);
		Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
		menuKeyField.setAccessible(true);
		menuKeyField.setBoolean(config, false);
	} catch (Exception e) {
		e.printStackTrace();
	}
}

六. 让Overflow显示图标

Google认为隐藏在overflow中的Action按钮都应该只显示文字,如果想显示图标,可以用反射的方法改变MenuBuilder这个类的setOptionalIconsVisible变量的值
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
	if (featureId == Window.FEATURE_ACTION_BAR && menu != null) {
		if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
			try {
				Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
				m.setAccessible(true);
				m.invoke(menu, true);
			} catch (Exception e) {
			}
		}
	}
	return super.onMenuOpened(featureId, menu);
}

七. 改变Overflow的图标

  <item
        android:id="@+id/action_search"
        android:actionViewClass="android.widget.SearchView"
        android:icon="@drawable/actionbar_search_icon"
        android:showAsAction="ifRoom|collapseActionView"
        android:title="@string/action_search"/>
    <item
        android:id="@+id/overflow_menus"
        android:actionProviderClass="@android:style/Widget.Holo.ActionButton.Overflow"
        android:orderInCategory="100"
        android:showAsAction="always"
        android:title="@string/action_search">
        <menu>
            <item
                android:id="@+id/action_plus"
                android:actionProviderClass="com.example.wechatsample.PlusActionProvider"
                android:icon="@drawable/actionbar_add_icon"
                android:showAsAction="ifRoom"
                android:title="@string/action_plus"/>
            <item
                android:id="@+id/action_album"
                android:icon="@drawable/ofm_photo_icon"
                android:title="@string/action_album"/>
            <item
                android:id="@+id/action_collection"
                android:icon="@drawable/ofm_collect_icon"
                android:title="@string/action_collection"/>
            <item
                android:id="@+id/action_card"
                android:icon="@drawable/ofm_card_icon"
                android:title="@string/action_card"/>
            <item
                android:id="@+id/action_settings"
                android:icon="@drawable/ofm_setting_icon"
                android:title="@string/action_settings"/>
            <item
                android:id="@+id/action_feed"
                android:icon="@drawable/ofm_feedback_icon"
                android:title="@string/action_feed"/>
        </menu>
    </item>
 

将要在Overflow内部显示的item用一个menu包裹起来,在onCreateOptionsMenu方法中调用menu.getItem(1).setIcon(R.drawable.actionbar_add_icon);

七. 自定义ActionBar

ActionBar actionBar = ((ActionBarActivity) getActivity()).getSupportActionBar();
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
View titleView = View.inflate(mContext, R.layout.title_mapmain, null);
titleView.setBackgroundColor(Color.WHITE);
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
actionBar.setCustomView(titleView,params)

八. 添加Action Provider

和Action View有点类似,Action Provider也可以将一个Action按钮替换成一个自定义的布局。

但不同的是,Action Provider能够完全控制事件的所有行为,并且还可以在点击的时候显示子菜单。

如何在一个Menu的Item中添加子菜单呢?

①.定义类继承ActionProvider,在menu.xml的item中通过actionProviderClass属性来引用所定义的类。

②.重写onPrepareSubMenu方法调用SubMenu的clear ,  add , setIcon ,setOnMenuItemClickListener方法来完成对子菜单的操作

③.重写hasSubMenu方法返回true

具体案例请参考文章最后提供的Demo。

九. 添加导航Tabs

Android官方更加推荐使用ActionBar中提供的Tabs功能,因为它更加的智能,可以自动适配各种屏幕的大小如何使用ActionBar提供的Tab功能?

①. 实现ActionBar.TabListener接口,这个接口提供了Tab事件的各种回调,比如当用户点击了一个Tab时,你就可以进行切换Tab的操作。②. 为每一个你想添加的Tab创建一个ActionBar.Tab的实例,并且调用setTabListener()方法来设置ActionBar.TabListener。除此之外,还需要调用setText()方法来给当前Tab设置标题。③. 最后调用ActionBar的addTab()方法将创建好的Tab添加到ActionBar中。

十. 自定义ActionBar样式

1. 使用主题

Theme.Holo,这是一个深色系的主题。Theme.Holo.Light,这是一个浅色系的主题。

2. 自定义背景

  如果想要修改ActionBar的背景,我们可以通过创建一个自定义主题并重写actionBarStyle属性来实现。这个属性可以指向另外一个样式,然后我们在这个样式中重写background这个属性就可以指定一个drawable资源或颜色,从而实现自定义背景的功能。在style.xml中添加

   <resources>
	    <style name="CustomActionBarTheme" parent="@android:style/Theme.Holo.Light">
	        <item name="android:actionBarStyle">@style/MyActionBar</item>
	    </style>
	
	    <style name="MyActionBar" parent="@android:style/Widget.Holo.Light.ActionBar">
	        <item name="android:background">#f4842d</item>			重写了background属性,并给它指定了一个背景色
	        <item name="android:backgroundStacked">#d27026</item>	重写了backgroundStacked属性,这个属性就是用于指定Tabs背景色的      
	    </style>			
	</resources>

然后在AndroidManifest.xml的Activity标签中声明android:theme="@style/CustomActionBarTheme"

3. 自定义文字颜色

 修改ActionBar标题颜色为白色

<style name="MyActionBar" parent="@android:style/Widget.Holo.Light.ActionBar">
    <item name="android:titleTextStyle">@style/MyActionBarTitleText</item>
</style>

<style name="MyActionBarTitleText" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title">
    <item name="android:textColor">#fff</item>
</style>

修改tab字体颜色

<style name="CustomActionBarTheme" parent="@android:style/Theme.Holo.Light">
    <item name="android:actionBarStyle">@style/MyActionBar</item>
    <item name="android:actionBarTabTextStyle">@style/MyActionBarTabText</item>
</style>

<style name="MyActionBarTabText"
       parent="@android:style/Widget.Holo.ActionBar.TabText">
    <item name="android:textColor">#fff</item>
</style>

4. 自定义Tab Indicator

为了可以明确分辨出我们当前选中的是哪一个Tab项,通常情况下都会在选中Tab的下面加上一条横线作为标识,这被称作Tab Indicator

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item  android:state_selected="false"
          android:state_pressed="false"
          android:drawable="@drawable/tab_unselected" />
    <item android:state_selected="true"
          android:state_pressed="false"
          android:drawable="@drawable/tab_selected" />
    <item android:state_selected="false"
          android:state_pressed="true"
          android:drawable="@drawable/tab_unselected_pressed" />
    <item android:state_selected="true"
          android:state_pressed="true"
          android:drawable="@drawable/tab_selected_pressed" />
</selector>
这里先是重写了actionBarTabStyle这个属性,并将它指向了另一个自定义样式MyActionBarTabs,接着在这个样式中重写background属性,然后指向我们刚才创建的actionbar_tab_indicator即可。
<resources>
    <style name="CustomActionBarTheme" parent="@android:style/Theme.Holo.Light">
        ......
        <item name="android:actionBarTabStyle">@style/MyActionBarTabs</item>
    </style>
    
    <style name="MyActionBarTabs" parent="@android:style/Widget.Holo.ActionBar.TabView">
        <item name="android:background">@drawable/actionbar_tab_indicator</item>
    </style>	
</resources>


最后在Actionbar使用的过程中还需要知道下面几个小知识点:

setHomeButtonEnabled:这个小于4.0版本的默认值为true的。但是在4.0及其以上是false,该方法的作用:决定左上角的图标是否可以点击

 // 给左上角图标的左边加上一个返回的图标 。对应ActionBar.DISPLAY_HOME_AS_UP

actionBar.setDisplayHomeAsUpEnabled(true)  

//使左上角图标是否显示,如果设成false,则没有程序图标,仅仅就个标题,否则,显示应用程序图标,对应id为android.R.id.home,对应ActionBar.DISPLAY_SHOW_HOME

actionBar.setDisplayShowHomeEnabled(true)   

//使自定义的普通View能在title栏显示,即actionBar.setCustomView能起作用,对应ActionBar.DISPLAY_SHOW_CUSTOM

actionBar.setDisplayShowCustomEnabled(true) 

//对应ActionBar.DISPLAY_SHOW_TITLE。

actionBar.setDisplayShowTitleEnabled(true)   

其中setHomeButtonEnabled和setDisplayShowHomeEnabled共同起作用,如果setHomeButtonEnabled设成false,即使setDisplayShowHomeEnabled设成true,图标也不能点击

下面给出3个Demo,让你彻底玩转ActionBar的使用。

下载Demo请猛戳


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值