Android之ActionBar(一)

少说多做,句句都会得到别人的重视;多说少做,句句都会受到别人的忽视。


本讲内容:ActionBar


一、ActionBar介绍

ActionBar是一种新増的导航栏功能,在Android 3.0之后加入到系统的API当中,是一个标识应用程序用户位置的窗口功能,并且给用户提供操作和导航模式

1)移除ActionBar的两种方式:

1、将theme指定成Theme.Holo.NoActionBar

2、在Activity中调用以下方法

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

修改Action Bar的图标和标题

 <activity
            android:name=".MainActivity"
            android:label="@string/hello_world"
            android:logo="@drawable/pic" >

示例一: 添加Action按钮
ActionBar可以根据应用程序当前的功能来提供与其相关的Action按钮,这些按钮都会以图标或文字的形式直接显示在ActionBar上。如果按钮过多,ActionBar上显示不完,多出的一些按钮可以隐藏在overflow里面(最右边的三个点就是overflow按钮),点击一下overflow按钮就可以看到全部的Action按钮了。当Activity启动的时候,系统会调用Activity的onCreateOptionsMenu()方法来取出所有的Action按钮,我们只需要在这个方法中去加载一个menu资源,并把所有的Action按钮都定义在资源文件里面就可以了。

下面是res/menu/main.xml  文件:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.example.actionbardemo.MainActivity" >

    <item
        android:id="@+id/action_edit"
        android:icon="@android:drawable/ic_menu_edit"
        app:showAsAction="always"
        android:title="@string/edit"/>
    <item
        android:id="@+id/action_delete"
        android:icon="@android:drawable/ic_menu_delete"
        app:showAsAction="always"
        android:title="@string/delete"/>
    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:title="@string/action_settings"
        android:icon="@android:drawable/ic_menu_set_as"
        app:showAsAction="never"/>

</menu>
其中id是该Action按钮的唯一标识符,icon用于指定该按钮的图标,title用于指定该按钮可能显示的文字(在图标能显示的情况下,通常不会显示文字),如果Action按钮在ActionBar中显示,用户可能通过长按该Action按钮的方式来查看到title的内容。 showAsAction则指定了该按钮显示的位置,主要有以下几种值可选:always表示永远显示在ActionBar中,如果屏幕空间不够则无法显示,ifRoom表示屏幕空间够的情况下显示在ActionBar中,不够的话就显示在overflow中,never则表示永远显示在overflow中。

注意:baritem显示出来
当界面继承ActionBarActivity写app:showAsAction="always"
当界面继承Activity写android:showAsAction="always"

下面是MainActivity.java主界面文件:
public class MainActivity extends ActionBarActivity {
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.action_edit:
			Toast.makeText(this, "action_edit", Toast.LENGTH_LONG).show();
			break;
		case R.id.action_delete:
			Toast.makeText(this, "action_delete", Toast.LENGTH_LONG).show();
			break;
		case R.id.action_settings:
			Toast.makeText(this, "action_settings", Toast.LENGTH_LONG).show();
			break;
		}
		return super.onOptionsItemSelected(item);
	}
}


示例二:通过Action Bar图标进行导航
启用ActionBar图标导航的功能,可以允许用户根据当前应用的位置来在不同界面之间切换。
 
       系统默认的图标                自己设置的图标
可以看到左上角的图标导航,可以实现返回上一个界面,与Back键不同之处,可以指定返回界面

实现ActionBar导航功能的三个步骤:
步骤一:调用setDisplayHomeAsUpEnabled()方法,并传入true
ActionBar actionBar=getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
步骤二:AndroidManifest.xml中配置父Activity
<activity  
    android:name=".MainActivity"  
    android:logo="@drawable/pic" >  
    <meta-data  
        android:name="android.support.PARENT_ACTIVITY"  
        android:value=".LaunchActivity" />  
</activity>
这里通过meta-data标签指定了MainActivity的父Activity是LaunchActivity,在Android 4.1版本之后,也可以直接使用android:parentActivityName这个属性来进行指定,如下所示:
 <activity
            android:name=".MainActivity"
            android:label="@string/hello_world"
            android:logo="@drawable/pic"
            android:parentActivityName=".LaunchActivity" >

步骤三: 对android.R.id.home事件进行一些特殊处理

下面是MainActivity.java主界面文件:
public class MainActivity extends ActionBarActivity {
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		ActionBar actionBar=getActionBar();
		actionBar.setDisplayHomeAsUpEnabled(true);
	}

	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		/**
		 * 其中,调用NavUtils.getParentActivityIntent()方法可以获取到跳转至父Activity的Intent,
		 * 然后如果父Activity和当前Activity是在同一个Task中的,则直接调用navigateUpTo()方法进行跳转,
		 * 如果不是在同一个Task中的,则需要借助TaskStackBuilder来创建一个新的Task。
		 */
		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);
			}
			break;
		}
		return super.onOptionsItemSelected(item);
	}
}


下面是res/values/styles文件(改变左上角的图标导航
 <style name="MyTheme" parent="AppBaseTheme">
          <item name="android:homeAsUpIndicator">@drawable/logo</item>
    </style>

下面是AndroidManifest.xml文件
 <activity
            android:name=".MainActivity"
            android:label="@string/hello_world"
            android:logo="@drawable/pic"
            android:theme="@style/MyTheme" 
            android:parentActivityName=".LaunchActivity" >



示例三:
添加Action View
ActionView它能在ActionBar直接显示一个具体的视图,如搜索框,而不只是一个Button。 为了声明一个ActionView,我们可以在menu资源中通过actionViewClass属性来指定一个控件,例如可以使用如下方式添加SearchView:

<item  
        android:id="@+id/action_search"  
        android:actionViewClass="android.widget.SearchView"  
        android:icon="@android:drawable/ic_menu_search"  
        android:showAsAction="ifRoom|collapseActionView"  
        android:title="@string/action_search"/>  
   
点击这个搜索按钮,这时SearchView就会展开占满整个ActionBar,而其它的Action按钮由于将showAsAction属性设置成了ifRoom,此时都会隐藏到overflow当中。

如果你希望在代码中对SearchView的属性进行配置(比如添加监听事件等),只需要在onCreateOptionsMenu()方法中获取该ActionView的实例就可以了,代码如下所示:
public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		MenuItem searchItem = menu.findItem(R.id.action_search);
		SearchView searchView = (SearchView) searchItem.getActionView();
		return true;
	}


示例四:设置Overflow按钮总是显示
系统会默认如果手机没有物理Menu键的话,overflow按钮就可以显示,如果有物理Menu键的话,overflow按钮就不会显示出来。实际上,在ViewConfiguration这个类中有一个叫做sHasPermanentMenuKey的静态变量,系统就是根据这个变量的值来判断手机有没有物理Menu键的。当然这是一个内部变量,我们无法直接访问它,但是可以通过反射的方式修改它的值,让它永远为false就可以了
private void setOverflowShow(){
		 try {  
		        ViewConfiguration config = ViewConfiguration.get(this);  
		        Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");  
		        menuKeyField.setAccessible(true);  
		        menuKeyField.setBoolean(config, false);  
		    } catch (Exception e) {  
		        e.printStackTrace();  
		    }  
	}
在onCreate()方法中调用setOverflowShow()方法就可以将sHasPermanentMenuKey设置成false了。

示例五:让Overflow中的选项显示图标

系统默认设置隐藏在overflow中的Action按钮只显示文字,不显示图片。实际上是由MenuBuilder这个类的setOptionalIconsVisible方法来决定的,默认 是false,如果我们通过反射在overflow被展开的时候给这个方法传入true,那么里面的每一个Action按钮对应的图标就都会显示出来了。
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);
	}
重写onMenuOpened()方法,当overflow被展开的时候就会回调这个方法。


示例六:添加Action Provider

添加一个Action Provider,我们需要在<item>标签中指定一个android:actionProviderClass属性,在里面填入Action Provider的完整类名。我们可以通过继承ActionProvider类的方式来创建一个自己的Action Provider,同时,Android也提供好了几个内置的Action Provider,比如说ShareActionProvider。由于每个Action Provider都可以自由地控制事件响应,所以它们不需要在onOptionsItemSelected()方法中再去监听点击事件,而是应该在onPerformDefaultAction()方法中去执行相应的逻辑。
   <item  
        android:id="@+id/action_share"  
        android:actionProviderClass="android.widget.ShareActionProvider"
        android:icon="@android:drawable/ic_menu_share"
        android:showAsAction="ifRoom"  
        android:title="@string/action_share"/>  

public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		MenuItem shareItem=menu.findItem(R.id.action_share);
		ShareActionProvider provider=(ShareActionProvider) shareItem.getActionProvider();
		provider.setShareIntent(getDefaultIntent());
		return true;
	}
	
	private Intent getDefaultIntent(){
		Intent intent=new Intent(Intent.ACTION_SEND);
		intent.setType("image/*");
		return intent;
	}
这里通过Intent来定义出你想分享哪些东西了,我们只需要在onCreateOptionsMenu()中调用MenuItem的getActionProvider()方法来得到该ShareActionProvider对象,再通过setShareIntent()方法去选择构建出什么样的一个Intent就可以了。

示例七:自定义Action Provider

<item  
        android:id="@+id/action_share"  
        android:actionProviderClass="com.example.actionbardemo.MyActionProvider"
        android:icon="@drawable/ic_launcher"
        android:showAsAction="ifRoom"  
        android:title="@string/action_share"/> 

注意导入的不是V4包,否则会报错
package com.example.actionbardemo;

import android.content.Context;
import android.view.ActionProvider;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.SubMenu;
import android.view.View;
import android.widget.Toast;

/**
 * 自定义Action Provider
 */
public class MyActionProvider extends ActionProvider {

	public MyActionProvider(Context context) {
		super(context);
	}

	public View onCreateActionView() {
		return null;
	}
	
	public void onPrepareSubMenu(SubMenu subMenu) {
		subMenu.clear();
		subMenu.add("sub item1").setIcon(R.drawable.ic_launcher).setOnMenuItemClickListener(new OnMenuItemClickListener() {
			public boolean onMenuItemClick(MenuItem item) {
				return true;
			}
		});
		subMenu.add("sub item2").setIcon(R.drawable.ic_launcher).setOnMenuItemClickListener(new OnMenuItemClickListener() {
			public boolean onMenuItemClick(MenuItem item) {
				return false;
			}
		});
	}
	
	/**
	 * 为了表示这个Action Provider是有子菜单的,需要重写hasSubMenu()方法并返回true,
	 * 然后在onPrepareSubMenu通过调用SubMenu的add()方法添加子菜单。
	 */
	public boolean hasSubMenu() {
		return true;
	}
}


示例八:使用主题

Android中有两个最基本的Activity主题可以用于指定ActionBar的颜色,分别是:
Theme.Holo,这是一个深色系的主题。
Theme.Holo.Light,这是一个浅色系的主题。

 

你可以将这些主题应用到你的整个应用程序,也可以只应用于某个Activity。通过在AndroidManifest.xml文件中给<application>或<activity>标签指定android:theme属性就可以实现了。比如:

<application android:theme="@android:style/Theme.Holo.Light"/>  


示例九: 自定义背景
1)修改ActionBar的背景,我们可以通过创建一个自定义主题并重写actionBarStyle属性来实现。这个属性可以指向另外一个样式,然后我们在这个样式中重写background这个属性就可以指定一个drawable资源或颜色,从而实现自定义背景的功能。

下面是res/values/styles.xml文件

<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>  
</style>

<application android:theme="@style/CustomActionBarTheme" >

定义一个CustomActionBarTheme主题,并让它继承自Theme.Holo.Light。然后在其内部重写了actionBarStyle这个属性,然后将这个属性指向了MyActionBar这个样式,我们在这个样式中又重写了background属性,并给它指定了一个背景色。效果如下图所示:



2)
自定义文字颜色:将文字颜色改成白色。


下面是res/values/styles.xml文件

<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.ActionBar">
        <item name="android:background">#f4842d</item>
        <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>
        <item name="android:textSize">17sp</item>
    </style>

<application android:theme="@style/CustomActionBarTheme" >



Take your time and enjoy it 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值