android官方文档学习之路---ActionBar

自学android有一定的时间了,由于自学的原因发现自己的知识很散,不够系统,因此想通过学习android官方文档和写博客的形式进行整理和总结,同时从中学到更多的知识。
由于本人是初学者的原因,难免会出现一些错误,希望大家谅解和指出。

概述

本篇主要写的是对actionBar的解析
参考:
1.android官方文档,文档所在目录为sdk/docs/index.html
2(http://blog.csdn.net/guolin_blog/article/details/18234477#reply)

ActionBar用于确定用户的位置并提供用户操作和导航模式

android官方文档学习之路---ActionBar_第1张图片

1.App icon 应用的图标,通过设置可以添加一个返回图标
2.Action Button 相当于普通的Button,可以监听点击事件
3.Action overflow ,可以显示隐藏的action button

actionBar的三个部分体现了actionBar的关键功能
确定当前位置,突出重要的功能(如上图的搜索),导航和视图切换

添加ActionBar

1.创建一个Activity并继承AppCompatAcitvity(取代ActionBarActivity)
2.在AndroidManifest中,将对Activity的theme进行设置

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

一般情况下创建activity是继承Activity的,可以对theme进行如下设置

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

这时候运行项目,就可以看到actionBar了。
既然有添加actionBar当然就会有移除actionBar,移除的方式有两种
1.将theme设置为带有NoActionBar的样式即可
2.添加如下代码

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

移除actionBar,实际上就是将其隐藏,因此可以通过show()的方式将actionBar再次显示出来。

添加ActionButton

所有的actionButton和action overflow里的item 都是在menu资源文件夹下的xml文件中定义的。
所以,我们需要创建一个xml文件
android官方文档学习之路---ActionBar_第2张图片
在新创建的文件中添加item

<menu xmlns:tools="http://schemas.android.com/tools"
      xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/action_search"
          android:icon="@drawable/ic_action_search"
          android:title="@string/action_search"
          android:actionViewClass="android.widget.SearchView"
          android:showAsAction="ifRoom|collapseActionView"
          tools:ignore="AppCompatResource"/>

    <item android:id="@+id/action_setting"
          android:title="@string/action_settings"
          android:icon="@mipmap/ic_launcher"
          android:showAsAction="never"
          tools:ignore="AppCompatResource"/>
menu>

所添加的item是显示在action overflow里面还是显示在actionBar上,可以通过showAsAction来进行设置。
Always:总是显示在actionBar上
IfRoom:如果actionBar上的还有空间,则显示在actionBar
Never:只显示在action overflow内
withText:如果你的menu item支持同时显示title和icon时,设置withText,就会同时 显示title和icon,比如如果设置ifRoom时默认只显示icon,加上withText时就会同时 显示title和icon。

android:showAsAction="withText|ifRoom"

特别注意的是:如果item显示在action overflow内时,即使你设置了title和icon,也 只会显示title不会显示icon,因为不特别设置的话,action overflow不会显示图片。
CollapseActionView:会在下面举例介绍

创建完毕后,我们就需要在actionBar上添加我们的action,这时候我们需要重载onCreateOptionsMenu()方法。

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

这样actionBar上就会出现我们在menu中定义的item,每个item可以被点击,但还缺少点击事件。
实现onOptionsItemSelected()方法给每个Item添加点击事件,与button实现点击方法类似。

@Override
public boolean onOptionsItemSelected(MenuItem item) {
   switch (item.getItemId())
   {
      case R.id.action_search:
         //....
         return true;
      case R.id.action_setting:
         //....
         return true;
      default:
         return super.onOptionsItemSelected(item);
   }
}

一般来说上面的操作加下面的一些方法,基本上可以实现常见的actionBar了。

①去除icon
如果activity继承自Activity,添加以下代码通过选择true和false显示和隐藏icon。

getActionBar().setDisplayShowHomeEnabled(false);

如果activity继承AppCompatActivity,原本就不会显示icon,要显示Icon必须添加以下代码。

ActionBar actionBar=getSupportActionBar();
actionBar.setLogo(R.mipmap.ic_launcher);
actionBar.setDisplayUseLogoEnabled(true);
actionBar.setDisplayShowHomeEnabled(true);

②显示导航按钮

ActionBar actionBar=getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);

这里写图片描述
通过上述代码我们会发现在actionBar上多了一个箭头,这时这部分就相当于一个按钮,可以被点击同时响应点击事件。
通常增加该按钮的目的是为了实现导航的功能,即实现页面的跳转。
当我们明确需要跳转的页面时可以通过以下代码来快速实现。

".SecondActivity"
    android:parentActivityName=".MainActivity">//想要返回的activity
    "android.support.PARENT_ACTIVITY"
        android:value=".MainActivity" />//想要返回的activity

在上述代码中我们明确在SecondActivity中点击导航按钮会返回到我们MainActivity中。
当然很多时候进入该activity的父activity是不确定的,因此我们可以重写getParentActivityIntent ()方法进行不同activity的跳转。

@Override
public Intent getParentActivityIntent() {
//常见的方式是通过获取getIntent传递过来的Intent中携带的数据
//根据该数据判断其对应的activity,之后创建新的intent指向该activity
   return intent;
}

返回的Intent就是我们点击后会实现的意图。这里我没有给出具体的代码,只是给出了实现的逻辑。因为实现的方法每个人都不同,但都很简单。
在测试这段代码时,无意间我发现一个很奇怪的事情

@Override
public Intent getParentActivityIntent() {
   Intent intent=new Intent();
   intent.setComponent(new ComponentName("aa","aa"));
   return intent;
}

通过setComponent,无论我填写的ComponentName的数据是什么,点击都能成功返回到上一个activity。一直搞不懂,求大牛说明下原因。

由于导航按钮也是actionBar上的一个item,所以我们也可以在onOptionsItemSelected()中实现它的点击事件。

@Override
public boolean onOptionsItemSelected(MenuItem item) {
   switch (item.getItemId())
   {
      case android.R.id.home://对应的Id
        //点击后要实现的代码
         return true;
      default:
         return super.onOptionsItemSelected(item);
   }
}

③在overflow中显示Icon
在上面提到overflow中默认是不显示Icon的,我们可以通过以下方法显示icon

rivate void setOverflowIconVisiable(Menu menu)//通过反射机制
{
   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) {
      }
   }
}
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
   if (menu!=null)
   {
      setOverflowIconVisiable(menu);
   }
   return super.onMenuOpened(featureId, menu);
}

添加一个actionView

一个ActionView是一个组件,用来替换ActionBar中的actionButton,可以在不用切换Activity和 Fragment并且不更换actionBar的情况下实现一些丰富的功能。
直接上例子

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/action_search"
          android:icon="@drawable/ic_action_search"
          android:title="@string/action_search"         android:actionViewClass="android.support.v7.widget.SearchView"
          android:showAsAction="ifRoom|collapseActionView"/>
    <item android:id="@+id/action_setting"
          android:title="@string/action_settings"
          android:icon="@mipmap/ic_launcher"
          android:showAsAction="never"/>
menu>

这里写图片描述
这里写图片描述
这里写图片描述

在showAsAction中添加collapseActionView选项
collapseActionView:通常与ifRoom一起使用,只会在设置了actionViewClass才会生效,它的作用是将actionViewClass设置的actionView折叠进actionButton中,当我们点击该actionButton时会将actionView展开
actionViewClass:指定一个组件作为actionView
例子中添加的是一个SearchView,当然我们也可以添加一个Button

android:actionViewClass="android.widget.Button"

注意:当我们将一个actionView折叠进一个actionButton中,我们就不需要对该actionButton实现点击事件,即我们在onOptionsItemSelected()中不该对actionButton进行响应,这是因为当我们点击actionButton时,系统依然会调用onOptionsItemSelected()。

成功在actionBar上显示了actionView,我们就需要响应事件

//从menu中获取search的Item
MenuItem searchItem=menu.findItem(R.id.action_search);
//再从Item中获取view
SearchView searchView=      (SearchView)searchItem.getActionView(); 
//得到view对象,之后想干什么就能干什么了

另外Android还实现了对actionView折叠和展开的监听

public boolean onCreateOptionsMenu(Menu menu) {
   MenuInflater inflater=getMenuInflater();
   inflater.inflate(R.menu.action_bar_menu,menu);
   //从menu中获取search的Item
   MenuItem searchItem=menu.findItem(R.id.action_search);
   MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
      @Override
      public boolean onMenuItemActionExpand(MenuItem item) 
      {
         return true;//true,展开actionView
      }

      @Override
     public boolean onMenuItemActionCollapse(MenuItem item) 
     {
         return true;//true,折叠actionView
      }
   });
   return super.onCreateOptionsMenu(menu);
}

添加Action Provider

与actionView类似,actionProvider用一个自定义的layout来代替actionButton,不同于actionView的是,actionProvider控制所有的action的行为并且当我们点击actionProvider会弹出子菜单。

我们可以通过继承ActionProvider类来自定义一个actionProvider。也可以使用android本身个给我们提供的一些actionProvider例如ShareActionProvider(实现分享)。

item android:id="@+id/action_share"
      android:title="@string/share"
      android:showAsAction="ifRoom"
      tools:ignore="AppCompatResource"   android:actionProviderClass="android.widget.ShareActionProvider"
    />

这时我们运行程序会发现多了个分享的button,当我们点击会发现并没有出现子菜单,这是因为我们还没定义子菜单中显示的内容。
在onCreateOptionMenu()中添加如下代码

MenuItem shareItem = menu.findItem(R.id.action_share);
ShareActionProvider mShareActionProvider = (ShareActionProvider)shareItem.getActionProvider();
mShareActionProvider.setShareIntent(getDefaultIntent());
private Intent getDefaultIntent() {
   Intent intent = new Intent(Intent.ACTION_SEND);
   intent.setType("image/*");
   return intent;
}

这里写图片描述

这里写图片描述

当我们点击子菜单中的Item后,会跳转到相应的界面。
除了使用ShareActionProvider之外,我们当然也可以自定义一个Action Provider,实现我们想要的功能。

public class MyActionProvider extends ActionProvider{

   private Context mContext;

   public MyActionProvider(Context context) {
      super(context);
      this.mContext=context;
   }
   @Override
   public View onCreateActionView() {
      LayoutInflater inflater=LayoutInflater.from(mContext);
      View view=inflater.inflate(R.layout.action_provider, null);
      Button btn= (Button) view.findViewById(R.id.button);
      btn.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
              Toast.makeText(mContext,
              "click",Toast.LENGTH_SHORT).show();
         }
      });
      return view;
   }
}

这里写图片描述

发现actionbar上多了一个按钮,当我们点击的该button时,发现并没有像ShareActionProvider一样弹出一个子菜单(这时候跟actionButton的作用很像)。
想要实现子菜单的弹出,可以这样写

@Override
public View onCreateActionView() {
   return null;//必须返回一个null,不然不会弹出子菜单
}
//必须重写该方法并返回true
@Override
public boolean hasSubMenu() {
   return true;
}

@Override
public void onPrepareSubMenu(SubMenu subMenu) {
   subMenu.clear();
   subMenu.add(0, 0, 0, "menu1")
  .setIcon(R.mipmap.ic_launcher)
  .setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() {
      @Override
      public boolean onMenuItemClick(MenuItem item) {
         Toast.makeText(mContext, "submenu1",    Toast.LENGTH_SHORT).show();
         return true;
      }
   });
   subMenu.add(0, 1, 1,"menu2")
  .setIcon(R.mipmap.ic_launcher)
  .setOnMenuItemClickListener(
  new MenuItem.OnMenuItemClickListener() {
      @Override
      public boolean onMenuItemClick(MenuItem item) {
         Toast.makeText(mContext, "submenu", Toast.LENGTH_SHORT).show();
         return true;
      }
   });
}

点击,发现出现了子菜单。
这里写图片描述

至此,我们可以成功的实现一个完整的actionBar,当然actionBar还提供了Tab导航和下拉式导航,这里就不叙述了(主要是我没用过,也没看见哪个app有用过,现在导航好像都是通过viewPager实现的,有需要的可以看官方文档)
提示:在写代码的时候,千万不能导错包

通过上面的方法创建的actionBar太过单一,我们也可以通过自定义actionBar,来实现我们想要的actionBar的样式

自定义actionBar

自定义actionBar的方式有很多,android本身提供了两种基本的activity主题。
Theme.Holo :一种”dark”的主题
这里写图片描述
Theme.Holo.Light:一种”light”的主题
这里写图片描述

我们也可以通过改变各种参数,实现不同的风格

actionBarStyle:
Baskground:设置actionBar的背景

<style name="MyActionBarStyle" parent="@android:style/Widget.Holo.Light.ActionBar">
    <item name="android:background">@color/orange
style>

这里写图片描述

ActionButtonStyle:设置actionButtonStyle的样式

<style name="MyActionButtonStyle"parent="@android:style/Widget.ActionButton">
    <item name="android:background">@color/green
style>

这里写图片描述

ActionOverflowButtonStyle:设置actionOverflowButtonStyle的样式

<style name="MyActionBarStyleOverflow" parent="@android:style/Widget.ActionButton.Overflow">
    <item name="android:src">@mipmap/ic_launcher
style>

这里写图片描述

TitleTextStyle:actionBar title的样式



这里写图片描述

这里我只是举了几个例子,关于样式的自定义还有很多,有兴趣的可以查询官方文档。

好了,到了这里关于actionBar的解析也就到了这里,当然本人水平,有限里面的内容绝大部分来源于android的官方文档,当然其中也有自己的一些理解。
在上面的内容中有一小部分内容也是第一次接触到,可能写的不是很准确,欢迎大家指出错误。
第一次写博客,花了很多时间,从中也收获了很多,希望自己能一直坚持下去(第一次多英文文档,有点痛苦,不过看着看着就习惯了,算是一种进步吧)

你可能感兴趣的:(android)