尊重原创:http://blog.csdn.net/yuanzeyao/article/details/39378825

关于ActionBar,相信大家并不陌生,可是真正能够熟练使用的也不是许多,这篇文章主要为大家具体介绍ActionBar的相关知识,ActionBar是在Android3.0中引入的概念,所以在2.x系统中使用ActionBar我们须要依赖ActionBarSherklock或者androi-support-v7库,ActionBarSherklock是anroid中很有名的一个开源项目,android-support-v7是Google后来推出的一个库,有了v7库后AndroidBarSherklock这个开源项目基本能够退出历史舞台了,在使用android-support-v7的过程中,一定不能仅仅使用它的jar包,由于它的jar包不包括一些重要的资源文件,我们必须导入android-support-v7project,然后让我们的project依赖它。

ActionBar的作用
1、帮助用户知道你如今处于哪个页面
2、为用户提供统一的导航界面

关于许多其它的ActionBar导航功能请參见 http://developer.android.com/guide/topics/ui/actionbar.html 我的这篇文章基本也是參考这里的

ActionBar在界面中的展现形式 例如以下图:

从图中能够看到一个ActionBar包括 APP icon,ActionItems,Action Overflow,事实上ActionBar基本就取代了曾经版本号中的菜单的概念,在不支持ActionBar的App中,假设你创建了菜单,当你点击菜单键时,下方会出来菜单,而在支持Actionbar的菜单中这些菜单向就出如今了ActionItem和Action Overflow里面了(具体请见后面),有些细心同学在平时可能会发现同一款App,在有些手机上出现了Overflow,而有些手机却没有,事实上这个是有规律的,在有菜单物理键的手机上是没有Overflow的,在没有物理菜单的手机上才有,事实上Google一直主张Android设备去掉物理菜单键,所以相信以后大部分手机都没有菜单物理键的,所以菜单的概念也会慢慢的淡化。

以下我们開始学习ActionBar吧 ,由于3.0之后的系统和2.x系统还是有略微的差别,所以我今天打算先讲讲2.x系统中ActionBar的使用,然后解说3.0之后系统ActionBar的使用。
这里我们就使用android-support-v7吧,毕竟它是Google推出来的。

在2.x上使用ActionBar的步骤

1、导入android-support-v7库,这个库事实上在你的sdk里面就有(前提是你已经下载下来了),如我的路径:D:\android-sdk-windows\extras\android\support\v7\appcompat
2、创建项目,让我们的库依赖andorid-support-v7,并让须要使用ActionBar的Activity依赖ActionBarActivity,并进行例如以下配置:

<activity android:theme="@style/Theme.AppCompat.Light" ... >

就这么简单,你的项目就已经引入了ActionBar了,假设你想隐藏ActionBar,例如以下操作就可以

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

这里要提醒一下:由于ActionBar在隐藏的时候会重现绘制Activity的界面,从而填充ActionBar的空白,所以当你频繁的隐藏和显示ActionBar时,会导致Activity的界面频繁重绘,为了避免这种情况发生,你能够再actionBarStyle中将 windowActionBarOverlay这个属性设置为true,也就是说ActionBar会在Activity的上面,隐藏和显示不会影响Activity

我上面引入的ActionBar没有引入不论什么内容,默认里面就是一个设置项,如今我们就像里面增加自己的item吧
创建res/menu/main_activity_actions.xml文件并增加例如以下内容,

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_copy"
android:icon="@drawable/copy"
android:title="复制"/>
<item
android:id="@+id/action_cut"
android:icon="@drawable/cut"
android:title="剪切"/>
<item
android:id="@+id/action_discard"
android:icon="@drawable/discard"
android:title="删除"/>
<item
android:id="@+id/action_edit"
android:icon="@drawable/edit"
android:title="编辑"/> <item
android:id="@+id/action_email"
android:icon="@drawable/email"
android:title="邮箱"/> </menu>

然后重写以下的方法:

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
//返回true才会显示overflowbutton
return true;
}

通过以上步骤,我们就已经向ActionBar中增加了5个Item,执行一下看看效果吧,例如以下图

ActionBar是出来了,可是和我们上面说的ActionBar貌似有些差别,这些item都进入了overflow了,另外就是我明明设置了icon属性,却没有看见icon
对于这两个问题,我们一一解决吧
item默认都是进入Overflow的,假设想有些重要的Item 进入ActionItem 里面,那么须要配置一个属性showAsAction

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
<item
android:id="@+id/action_copy"
android:icon="@drawable/copy"
android:title="复制"
yourapp:showAsAction="always" />
...
</menu>

注意这里的showAsActoin命名空间是自己定义的,不是"android",由于这个属性在2.x系统中没有,是andorid-support-v7定义的,你执行一下,会发现复制已经到了ActionItem的位置了

第二个问题就是设置了icon为什么没有显示?事实上在Actionbar中,处于ActionItem位置的item默认是显示icon而不显示title的,我们能够通过在showAsActoin中配置"always|withText",让Tiele显示出来(可是也不一定会显示,仅仅是尽量显示),而处于Overflow的item 默认是显示title而不显示icon的,这个能够通过反射机制来改变,方案例如以下:

public void setOverflowIconVisiable(Menu menu)
{
try
{
Class clazz=Class.forName("com.android.internal.view.menu.MenuBuilder");
Field field=clazz.getDeclaredField("mOptionalIconsVisible");
if(field!=null)
{
field.setAccessible(true);
field.set(menu , true);
}
} catch (ClassNotFoundException e)
{
e.printStackTrace();
} catch (NoSuchFieldException e)
{
e.printStackTrace();
} catch (IllegalArgumentException e)
{
e.printStackTrace();
} catch (IllegalAccessException e)
{
e.printStackTrace();
} }

然后再onMenuOpened方法中调用

 @Override
public boolean onMenuOpened(int featureId, Menu menu)
{ if(featureId == Window.FEATURE_ACTION_BAR && menu != null)
{
setOverflowIconVisiable(menu);
} return super.onMenuOpened(featureId, menu);
}

执行效果例如以下图,能够看到icon已经显示了

眼下这些ActionItem和Overflowsitems都是没有响应事件的,如今为他们增加吧,假设曾经使用过菜单的同学会认为和菜单是一样的

 @Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch(item.getItemId())
{
case R.id.action_copy:
Toast.makeText(this, item.getTitle(), 1000).show();
return true;
case R.id.action_cut:
Toast.makeText(this, item.getTitle(), 1000).show();
return true;
case R.id.action_delete:
Toast.makeText(this, item.getTitle(), 1000).show();
return true;
case R.id.action_edit:
Toast.makeText(this, item.getTitle(), 1000).show();
return true;
case R.id.action_email:
Toast.makeText(this, item.getTitle(), 1000).show();
return true;
}
return super.onOptionsItemSelected(item);
}

Fragment中增加ActionItem

接下来学习一下在Fragment里面使用ActionItem吧

public class MyFragment extends Fragment
{
private static final String TAG = "MyFragment"; @Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//一定要调用,否则无法将菜单增加ActionItem
setHasOptionsMenu(true);
} @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{ TextView tv=new TextView(this.getActivity());
tv.setText("Hello Gavin");
return tv;
} @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
inflater.inflate(R.menu.fragment_men, menu);
super.onCreateOptionsMenu(menu, inflater);
} @Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch(item.getItemId())
{
case R.id.action_share:
Toast.makeText(this.getActivity(), item.getTitle(), 1000).show();
return true; }
return super.onOptionsItemSelected(item);
}
}

使用上和Activity差点儿相同,有一点须要注意,对于菜单的响应事件,Activity优于Fragment响应,所以在Activity的onOptionsItemSelected方法中对于没有处理的事件须要调用super.onOptionsItemSelected(item)(也能够是false,可是推荐前者),假设返回true,那么Fragment是不会执行onOptionsItemSelectedd的。

将ActionBar置于屏幕下方
假设须要将ActionBar置于屏幕下方,那么仅仅须要例如以下配置就可以

<manifest ...>
<activity ... >
<meta-data android:name="android.support.UI_OPTIONS"
android:value="splitActionBarWhenNarrow" />
</activity>
</manifest>

ActionBar的导航功能

ActionBar最重要的功能就是其导航功能,使用其导航功能时,须要进行例如以下配置
1、显示导航button
ActionBar actionBar = getSupportActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
配置完了后,执行例如以下图,你会发现Actionbar多了一个相似返回的icon

2、为导航增加事件
在onOptionsItemSelected方法中增加例如以下分支推断
case android.R.id.home:
        finish();
        return true;
这个是最简单的处理,就是finish掉自身,许多其它强大的导航功能请參见后面

看到上面的导航功能预计许多同学会认为它的功能和物理返回键的功能不是一样吗?假设依照我上面的实现,确实差点儿相同,可是ActionBar真正的意图不是这种,我们知道物理返回键时依据Activity栈回退到前一个Activity,是不能直接回退到前前一个Activity的,可是ActionBar是能够的,以下就来实现以下吧

实现这个导航功能有两种实现方式
a、为当前Activity指定父Activity
b、重写 getSupportParentActivityIntent() 和onCreateSupportNavigateUpTaskStack()

当中a比較适合须要返回的父Activity比較 固定,不会由于上下文环境而改变,实现也简单,仅仅须要进行例如以下配置

<activity
android:name="com.action.demo.SecondActivity"> <meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.action.demo.MainActivity" /> </activity>

并重写SecondActivity的  onOptionsItemSelected方法

@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch(item.getItemId())
{
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;
}
return super.onOptionsItemSelected(item);
}

b比較适合依据上下文环境选择导航到某一个Activity,比如,能够分别从MainActivity,ThreeActivity进入到SecondActivity,那么将来源标记为1和2(通过Intent 传递),重写getSupportParentActivityIntent

 @Override
public Intent getSupportParentActivityIntent()
{
if(from==1)
{
return new Intent().setClassName(this.getPackageName(), "com.action.demo.ThreeActivity");
}else if(from==2)
{
return new Intent().setClassName(this.getPackageName(), "com.action.demo.ThreeActivity");
} return super.getSupportParentActivityIntent();
}

这样便能够动态的实现导航

增加ActionView

一个ActionView就是一个Widget,用来替换ActionBar中的一些button,能够在不用切换Activity和 Fragment的情况下实现一些丰富的功能,以下使用SearchView来作为样例解说ActionView的使用
   在main.xml中增加item

 <item android:id="@+id/action_search"
android:title="搜索"
android:icon="@drawable/search"
myapp:showAsAction="ifRoom|collapseActionView"
myapp:actionViewClass="android.support.v7.widget.SearchView" />

然后在onCreateOptionsMenu中增加例如以下代码

 MenuItem searchItem=menu.findItem(R.id.action_search);
final SearchView searchView=(SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setOnQueryTextListener(new OnQueryTextListener()
{ @Override
public boolean onQueryTextSubmit(String arg0)
{
Toast.makeText(MainActivity.this, arg0, 1000).show();
searchView.onActionViewCollapsed();
return true;
} @Override
public boolean onQueryTextChange(String arg0)
{
return false;
}
});

增加Action Provider

Action Provider和Action View 有些相似,和Action View不同的是当Action Provider按下的时候能够显示子菜单。以下使用ShareActionProvider为例解说ActionProvider的使用

<item android:id="@+id/action_share1"
android:title="分享"
myapp:showAsAction="ifRoom"
myapp:actionProviderClass="android.support.v7.widget.ShareActionProvider"
/>

在onCreateOptionsMenu中增加例如以下代码

ShareActionProvider mShareActionProvider = (ShareActionProvider)
MenuItemCompat.getActionProvider(menu.findItem(R.id.action_share1));
mShareActionProvider.setShareIntent(getDefaultIntent());

执行效果例如以下图:

ShareActionProvider是Android系统自带的一个Provider,以下我们试试自己定义的Provider,我们来模仿微信中的右側的“+”号功能
public class CustomActionProvider extends ActionProvider
{
private static final String TAG = "CustomActionProvider";
public CustomActionProvider(Context context)
{
super(context);
} @Override
public View onCreateActionView()
{
return null;//LayoutInflater.from(getContext()).inflate(R.layout.provider_layout, null);
}
//这种方法是点击“+”号会默认执行的地方,注意这种方法能够被onOptionsItemSelected方法拦截掉
@Override
public boolean onPerformDefaultAction()
{
Toast.makeText(this.getContext(), "onPerformDefaultAction", 1000).show();
return super.onPerformDefaultAction();
} @Override
public void onPrepareSubMenu(SubMenu subMenu)
{
super.onPrepareSubMenu(subMenu);
subMenu.clear();
subMenu.add("发起群聊").setIcon(R.drawable.alluser).setOnMenuItemClickListener(new OnMenuItemClickListener()
{ @Override
public boolean onMenuItemClick(MenuItem item)
{
return true;
}
});
}
//一定要重写该方法,并返回true,否则不会出现子菜单
@Override
public boolean hasSubMenu()
{
return true;
} }

在ActionBar中增加Tab

使用ActionBar中的Tab功能,使用ActionBar中的Tab功能很easy

ActionBar bar=this.getSupportActionBar();
bar.setDisplayHomeAsUpEnabled(true);
bar.setDisplayShowTitleEnabled(false);
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.addTab(bar.newTab().setText("电影").setTabListener(this));
bar.addTab(bar.newTab().setText("电视剧").setTabListener(this));
bar.addTab(bar.newTab().setText("直播").setTabListener(this));

效果例如以下图

ActionBar的Style和Theme

在学习ActionBar的style和Theme之前,我们先来了解一下Style和Theme是啥吧,Style即使一些属性的集合,相似于css文件(前端开发的同学都很熟悉),Theme事实上就是Style,仅仅只是Theme是用于Activity的Style,在Android系统中自带了许多了Theme,这些Theme中有的有ActionBar,有的没有ActionBar,对于没有Actionbar的Theme对于的Activity,当调用getSupportActoin时返回null,

尽管说ActionBar是为用户提供的统一的导航功能,可是这个并不意味着全部的ActionBar都长一个样,我们还是能够依据需求进行定制的,以下我们就来学习定制自己的ActionBar
在学习自己定义ActionBar之前给大家推荐一个网址:http://jgilfelt.github.io/android-actionbarstylegenerator/  能够帮助我们进行定制ActionBar

这里我先给出竖屏和横屏的效果图,然后给出style文件,ActionBar的style属性许多,我们仅仅须要知道一些比較经常使用的,然后知道怎么查询这个属性就可以了,我能够到http://developer.android.com/guide/topics/ui/actionbar.html  ActionBar许多其它属性的使用

效果图例如以下:
竖屏图:
横屏图:
style.xml
<style name="MyActionBarTheme" parent="@style/Theme.AppCompat">

       	<item name="android:actionBarStyle">@style/ActionBarStyle</item>
<item name="android:actionMenuTextColor">@color/menu_color</item>
<item name="android:windowActionBarOverlay">false</item>
<item name="android:itemBackground">@drawable/action_item_bg_selector</item>
<item name="android:actionOverflowButtonStyle">@style/ActionBarOverflowStyle</item>
<item name="android:actionBarTabTextStyle">@style/TabTextStyle</item>
<item name="android:actionBarTabStyle">@style/ActionBarTab</item> <!--Support Library-->
<item name="actionBarStyle">@style/ActionBarStyle</item>
<item name="actionMenuTextColor">@color/menu_color</item>
<item name="windowActionBarOverlay">false</item>
<item name="actionOverflowButtonStyle">@style/ActionBarOverflowStyle</item>
<item name="actionBarTabTextStyle">@style/TabTextStyle</item>
<item name="actionOverflowButtonStyle">@style/ActionBarOverflowStyle</item>
<item name="actionBarTabStyle">@style/ActionBarTab</item>
</style> <style name="ActionBarStyle" parent="@style/Widget.AppCompat.ActionBar">
<item name="android:background">@drawable/action_back</item>
<item name="android:titleTextStyle">@style/TitleTextStyle</item>
<item name="background">@drawable/action_back</item>
<item name="titleTextStyle">@style/TitleTextStyle</item>
<item name="backgroundStacked">@drawable/action_back_stack</item>
<item name="backgroundSplit">@drawable/action_back_stack</item> </style> <style name="TitleTextStyle"
parent="@style/TextAppearance.AppCompat.Widget.ActionBar.Title">
<item name="android:textColor">@color/actionbar_text</item>
</style> <style name="TabTextStyle"
parent="@style/Widget.AppCompat.ActionBar.TabText">
<item name="android:textColor">@color/actionbar_text</item>
<item name="android:textSize">15sp</item>
<item name="android:textStyle">normal</item>
<item name="android:maxLines">1</item>
</style> <style name="ActionBarOverflowStyle" parent="Widget.AppCompat.ActionButton.Overflow">
<item name="android:src">@drawable/more</item> </style> <style name="ActionBarTab" parent="Widget.AppCompat.ActionBar.TabView">
<item name="android:background">@drawable/tab_indicator</item>
</style>

细心的同学会发现这里每一个属性声明了两遍(个别仅仅有一个),这是由于我们使用的是support-library-v7库,带前缀“android:”的是相应Android系统的,没有这个前缀的是support-librayr的。

最后给出tab_indicator的定义,这个是tab指示器的背景图片,这个并非我手动写的,我是利用上面给出的网址生成的。

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Non focused states -->
<item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@android:color/transparent" />
<item android:state_focused="false" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/tab_selected" /> <!-- Focused states -->
<item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/tab_unselected_focused" />
<item android:state_focused="true" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/tab_selected_focused" /> <!-- Pressed -->
<!-- Non focused states -->
<item android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed" />
<item android:state_focused="false" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed" /> <!-- Focused states -->
<item android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed" />
<item android:state_focused="true" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed" />
</selector>

先写到这里吧,大家有哪里没有看明确的地方欢迎留言....

Android导航栏ActionBar的具体分析的更多相关文章

  1. Android官方导航栏ActionBar(二)—— Action View、Action Provider、Navigation Tabs的详细用法

    在上一篇文章(Android之官方导航栏ActionBar)中,我们介绍了ActionBar各组成部分的基本应用.ActionBar除了提供Action Buttons外,还提供了多种导航方式如 Ac ...

  2. Bootstrap导航栏navbar源码分析

    1.本文目地:分析bootstrap导航栏及其响应式的实现方式,提升自身css水平 先贴一个bootstrap的导航栏模板 http://v3.bootcss.com/examples/navbar- ...

  3. unity 显示、隐藏Android导航栏

    1.下面的返回.home栏可用Screen.fullScreen控制 2.导航栏的显示和隐藏用下面代码控制 private AndroidJavaObject currentActivity { ge ...

  4. react-native react-navigation StackNavigator android导航栏 标题下居中

    navigationOptions:({ navigation }) => ({ , textAlign:'center' }}) 如上设置即可,如果有返回箭头,那么右边也要加一个 占位的或者设 ...

  5. Android之官方导航栏ActionBar

    一.ActionBar概述 ActionBar是android3.0以后新增的组件,主要用于标示应用程序以及用户所处的位置并提供相关操作以及全局的导航功能.下面我们就看看如何使用ActionBar,真 ...

  6. android之官方导航栏ActionBar(三)之高仿优酷首页

    一.问题概述 通过上两篇文章,我们对如何使用ActionBar大致都已经有了认识.在实际应用中,我们更多的是定制ActionBar,那么就需要我们重写或者定义一些样式来修饰ActionBar,来满足具 ...

  7. Android导航栏菜单强制转换

    private void getOverflowMenu() { ViewConfiguration viewConfig = ViewConfiguration.get(this); try { F ...

  8. React Navigation 导航栏样式调整+底部角标消息提示

    五一佳节匆匆而过,有人选择在外面看人山人海,有人选择宅在家中度过五一,也有人依然坚守在第一线,致敬! 这是坚持学习react-native的第二篇文章,可能会迟到,但是绝不会缺席,这篇要涉及到的是re ...

  9. Android ActionBar完全解析,使用官方推荐的最佳导航栏(下) .

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/25466665 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工 ...

随机推荐

  1. codeforces 659D . Bicycle Race 几何

    题目链接 对相邻的三个点叉积判断一下就好. #include <iostream> #include <vector> #include <cstdio> #inc ...

  2. 自定义Edit控件控制输入范围

    //自定义Edit,实现十六进制输入控制,使用OnChar()函数实现 //MyEdit.h #pragma once class CMyEdit : public CEdit { DECLARE_D ...

  3. ADO.NET入门

    什么是ADO.NET ADO.NET就是一组类库,这组类库可以让我们通过程序的方式访问数据库,就像System.IO下的类用类操作文件一样, System.Data.这组类是用来操作数据库(不光是MS ...

  4. J2SE知识点摘记(二十一)

    实现原理 前面已经提了一下Collection的实现基础都是基于数组的.下面我们就已ArrayList 为例,简单分析一下ArrayList 列表的实现方式.首先,先看下它的构造函数. 下列表格是在S ...

  5. Oracle EBS-SQL (SYS-20):OPM接口处理.sql

    /* 未加工的材料交易(必须解决) UNcosted Transactions (must resolve) 无成本的交易(必须解决) Pending WIP costing transactions ...

  6. [LeetCode][Python]Palindrome Number

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com'https://oj.leetcode.com/problems/palindr ...

  7. js中的刷新方法

    刷新并清除缓存: location.reload(true); 返回上一页并刷新: history.go(-1); location.reload(true); 子页面刷新父页面: self.open ...

  8. Android中的数据存储

    Android中的数据存储主要分为三种基本方法: 1.利用shared preferences存储一些轻量级的键值对数据. 2.传统文件系统. 3.利用SQLite的数据库管理系统. 对SharedP ...

  9. 浅谈Qt事件的路由机制:鼠标事件

    请注意,本文是探讨文章而不是教程,是根据实验和分析得出的结果,可能是错的,因此欢迎别人来探讨和纠正. 这几天对于Qt的事件较为好奇,平时并不怎么常用,一般都是用信号,对于事件的处理,一般都是需要响应键 ...

  10. Spring Jdbc使用like模糊查询

    public List<WfConfigMVO> queryList(WfConfigMVO wfConfig) throws SysException { StringBuffer sq ...