【转】Android ActionBar完全解析,使用官方推荐的最佳导航栏(上)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了【转】Android ActionBar完全解析,使用官方推荐的最佳导航栏(上),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含11981字,纯文字阅读大概需要18分钟。
内容图文
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/18234477
本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工,英文好的朋友也可以直接去读原文。
http://developer.android.com/guide/topics/ui/actionbar.html
Action Bar是一种新増的导航栏功能,在Android 3.0之后加入到系统的API当中,它标识了用户当前操作界面的位置,并提供了额外的用户动作、界面导航等功能。使用ActionBar的好处是,它可以 给提供一种全局统一的UI界面,使得用户在使用任何一款软件时都懂得该如何操作,并且ActionBar还可以自动适应各种不同大小的屏幕。下面是一张使 用ActionBar的界面截图:
其中,[1]是ActionBar的图标,[2]是两个action按钮,[3]是overflow按钮。
由于Action Bar是在3.0以后的版本中加入的,如果想在2.x的版本里使用ActionBar的话则需要引入Support Library,不过3.0之前版本的市场占有率已经非常小了,这里简单起见我们就不再考虑去做向下兼容,而是只考虑4.0以上版本的用法。
添加和移除Action Bar
ActionBar 的添加非常简单,只需要在AndroidManifest.xml中指定Application或Activity的theme是Theme.Holo或 其子类就可以了,而使用Eclipse创建的项目自动就会将Application的theme指定成Theme.Holo,所以ActionBar默认 都是显示出来的。新建一个空项目并运行,效果如下图所示:
而如果想要移除ActionBar的话通常有两种方式,一是将theme指定成Theme.Holo.NoActionBar,表示使用一个不包含ActionBar的主题,二是在Activity中调用以下方法:
1 ActionBar actionBar = getActionBar(); 2 actionBar.hide();
现在重新运行一下程序,就可以看到ActionBar不再显示了,如下图所示:
修改Action Bar的图标和标题
默 认情况下,系统会使用<application>或者<activity>中icon属性指定的图片来作为ActionBar的 图标,但是我们也可以改变这一默认行为。如果我们想要使用另外一张图片来作为ActionBar的图标,可以在<application>或 者<activity>中通过logo属性来进行指定。比如项目的res/drawable目录下有一张weather.png图片,就可以 在AndroidManifest.xml中这样指定:>
1 < activity 2 android:name ="com.example.actionbartest.MainActivity" 3 android:logo ="@drawable/weather" > 4 </ activity >
现在重新运行一下程序,效果如下图所示:
OK,ActionBar的图标已经修改成功了,那么标题中的内容该怎样修改呢?其实也很简单,使用label属性来指定一个字符串就可以了,如下所示:
1 < activity 2 android:name ="com.example.actionbartest.MainActivity" 3 android:label ="天气" 4 android:logo ="@drawable/weather" > 5 </ activity >
添加Action按钮
那么我们先来看下menu资源文件该如何定义,代码如下所示:
1 < menu xmlns:android ="http://schemas.android.com/apk/res/android" 2 xmlns:tools ="http://schemas.android.com/tools" 3 tools:context ="com.example.actionbartest.MainActivity" > 4 5 < item 6 android:id ="@+id/action_compose" 7 android:icon ="@drawable/ic_action_compose" 8 android:showAsAction ="always" 9 android:title ="@string/action_compose" /> 10 < item 11 android:id ="@+id/action_delete" 12 android:icon ="@drawable/ic_action_delete" 13 android:showAsAction ="always" 14 android:title ="@string/action_delete" /> 15 < item 16 android:id ="@+id/action_settings" 17 android:icon ="@drawable/ic_launcher" 18 android:showAsAction ="never" 19 android:title ="@string/action_settings" /> 20 21 </ menu >
可以看到,这里我们通过三个<item>标签定义了三个Action按 钮。<item>标签中又有一些属性,其中id是该Action按钮的唯一标识符,icon用于指定该按钮的图标,title用于指定该按钮 可能显示的文字(在图标能显示的情况下,通常不会显示文字),showAsAction则指定了该按钮显示的位置,主要有以下几种值可选:always表 示永远显示在ActionBar中,如果屏幕空间不够则无法显示,ifRoom表示屏幕空间够的情况下显示在ActionBar中,不够的话就显示在 overflow中,never则表示永远显示在overflow中。接着,重写Activity的onCreateOptionsMenu()方法,代码如下所示:
@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main, menu); returnsuper.onCreateOptionsMenu(menu); }
这部分代码很简单,仅仅是调用了MenuInflater的inflate()方法来加载menu资源就可以了。现在重新运行一下程序,结果如下图所示:
- 当ActionBar中的剩余空间不足的时候,如果Action按钮指定的showAsAction属性是ifRoom的话,该Action按钮就会出现在overflow当中,此时就只有title能够显示了。
- 如果Action按钮在ActionBar中显示,用户可能通过长按该Action按钮的方式来查看到title的内容。
响应Action按钮的点击事件
当 用户点击Action按钮的时候,系统会调用Activity的onOptionsItemSelected()方法,通过方法传入的MenuItem参 数,我们可以调用它的getItemId()方法和menu资源中的id进行比较,从而辨别出用户点击的是哪一个Action按钮,比如:
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_compose: Toast.makeText( this, "Compose", Toast.LENGTH_SHORT).show(); returntrue; case R.id.action_delete: Toast.makeText(this, "Delete", Toast.LENGTH_SHORT).show(); returntrue; case R.id.action_settings: Toast.makeText(this, "Settings", Toast.LENGTH_SHORT).show(); returntrue; default: returnsuper.onOptionsItemSelected(item); } }
可以看到,我们让每个Action按钮被点击的时候都弹出一个Toast,现在重新运行一下代码,结果如下图所示:
通过Action Bar图标进行导航
我们可以通过调用setDisplayHomeAsUpEnabled()方法来启用ActionBar图标导航功能,比如:
1 @Override 2 protected void onCreate(Bundle savedInstanceState) { 3 super .onCreate(savedInstanceState); 4 setTitle("天气"); 5 setContentView(R.layout.activity_main); 6 ActionBar actionBar = getActionBar(); 7 actionBar.setDisplayHomeAsUpEnabled(true); 8 }
现在重新运行一下程序,结果如下图所示:
可以看到,在ActionBar图标的左侧出现了一个向左的箭头,通常情况下这都表示返回的意思,因此最简单的实现就是在它的点击事件里面加入finish()方法就可以了,如下所示:
1 @Override 2 public boolean onOptionsItemSelected(MenuItem item) { 3 switch (item.getItemId()) { 4 case android.R.id.home: 5 finish(); 6 return true ; 7 …… 8 } 9 }
当点击ActionBar图标的时候,系统同样会调用onOptionsItemSelected()方法,并且此时的itemId是android.R.id.home,所以finish()方法也就是加在这里的了。
第二步需要在AndroidManifest.xml中配置父Activity,如下所示:
1 < activity 2 android:name ="com.example.actionbartest.MainActivity" 3 android:logo ="@drawable/weather" > 4 < meta-data 5 android:name ="android.support.PARENT_ACTIVITY" 6 android:value ="com.example.actionbartest.LaunchActivity" /> 7 </ activity >
可以看到,这里通过meta-data标签指定了MainActivity的父Activity是LaunchActivity,在Android 4.1版本之后,也可以直接使用android:parentActivityName这个属性来进行指定,如下所示:
1 < activity 2 android:name ="com.example.actionbartest.MainActivity" 3 android:logo ="@drawable/weather" 4 android:parentActivityName ="com.example.actionbartest.LaunchActivity" > 5 </ activity >
第三步则需要对android.R.id.home这个事件进行一些特殊处理,如下所示:
1 @Override 2 public boolean onOptionsItemSelected(MenuItem item) { 3 switch (item.getItemId()) { 4 case android.R.id.home: 5 Intent upIntent = NavUtils.getParentActivityIntent(this); 6if (NavUtils.shouldUpRecreateTask(this, upIntent)) { 7 TaskStackBuilder.create(this) 8 .addNextIntentWithParentStack(upIntent) 9 .startActivities(); 10 } else { 11 upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 12 NavUtils.navigateUpTo(this, upIntent); 13 } 14returntrue; 15 ...... 16 } 17 }
其中,调用NavUtils.getParentActivityIntent()方法 可以获取到跳转至父Activity的Intent,然后如果父Activity和当前Activity是在同一个Task中的,则直接调用 navigateUpTo()方法进行跳转,如果不是在同一个Task中的,则需要借助TaskStackBuilder来创建一个新的Task。
添加Action View
为了声明一个ActionView,我们可以在menu资源中通过actionViewClass属性来指定一个控件,例如可以使用如下方式添加SearchView:
1 < menu xmlns:android ="http://schemas.android.com/apk/res/android" > 2 3 < item 4 android:id ="@+id/action_search" 5 android:icon ="@drawable/ic_action_search" 6 android:actionViewClass ="android.widget.SearchView" 7 android:showAsAction ="ifRoom|collapseActionView" 8 android:title ="@string/action_search" /> 9 ...... 10 11 </ menu >
注意在showAsAction属性中我们还声明了一个collapseActionView,这个值表示该控件可以被合并成一个Action按钮。
如果你还希望在代码中对SearchView的属性进行配置(比如添加监听事件等),完全没有问题,只需要在onCreateOptionsMenu()方法中获取该ActionView的实例就可以了,代码如下所示:
1 @Override 2 public boolean onCreateOptionsMenu(Menu menu) { 3 MenuInflater inflater = getMenuInflater(); 4 inflater.inflate(R.menu.main, menu); 5 MenuItem searchItem = menu.findItem(R.id.action_search); 6 SearchView searchView = (SearchView) searchItem.getActionView(); 7// 配置SearchView的属性 8 ...... 9returnsuper.onCreateOptionsMenu(menu); 10 }
在得到了SearchView的实例之后,就可以任意地配置它的各种属性了。关于SearchView的更多详细用法,可以参考官方文档 http://developer.android.com/guide/topics/search/search-dialog.html 。除此之外,有些程序可能还希望在ActionView展开和合并的时候显示不同的界面,其实我们只需要去注册一个ActionView的监听器就能实现这样的功能了,代码如下所示:
1 @Override 2 public boolean onCreateOptionsMenu(Menu menu) { 3 MenuInflater inflater = getMenuInflater(); 4 inflater.inflate(R.menu.main, menu); 5 MenuItem searchItem = menu.findItem(R.id.action_search); 6 searchItem.setOnActionExpandListener(new OnActionExpandListener() { 7 @Override 8publicboolean onMenuItemActionExpand(MenuItem item) { 9 Log.d("TAG", "on expand"); 10returntrue; 11 } 1213 @Override 14publicboolean onMenuItemActionCollapse(MenuItem item) { 15 Log.d("TAG", "on collapse"); 16returntrue; 17 } 18 }); 19returnsuper.onCreateOptionsMenu(menu); 20 }
可以看到,调用MenuItem的 setOnActionExpandListener()方法就可以注册一个监听器了,当SearchView展开的时候就会回调 onMenuItemActionExpand()方法,当SearchView合并的时候就会调用 onMenuItemActionCollapse()方法,我们在这两个方法中进行相应的UI操作就可以了。
Overflow按钮不显示的情况
实 际上,在ViewConfiguration这个类中有一个叫做sHasPermanentMenuKey的静态变量,系统就是根据这个变量的值来判断手 机有没有物理Menu键的。当然这是一个内部变量,我们无法直接访问它,但是可以通过反射的方式修改它的值,让它永远为false就可以了,代码如下所 示:
1 @Override 2 protected void onCreate(Bundle savedInstanceState) { 3 ...... 4 setOverflowShowingAlways(); 5 } 6 7 private void setOverflowShowingAlways() { 8 try { 9 ViewConfiguration config = ViewConfiguration.get(this); 10 Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey"); 11 menuKeyField.setAccessible(true); 12 menuKeyField.setBoolean(config, false); 13 } catch (Exception e) { 14 e.printStackTrace(); 15 } 16 }
这里我们在onCreate()方法的最后调用了setOverflowShowingAlways()方法,而这个方法的内部就是使用反射的方式将sHasPermanentMenuKey的值设置成false,现在重新运行一下代码,结果如下图所示:
让Overflow中的选项显示图标
其 实,overflow中的Action按钮应不应该显示图标,是由MenuBuilder这个类的setOptionalIconsVisible方法来 决定的,如果我们在overflow被展开的时候给这个方法传入true,那么里面的每一个Action按钮对应的图标就都会显示出来了。调用的方法当然 仍然是用反射了,代码如下所示:
1 @Override 2 public boolean onMenuOpened(int featureId, Menu menu) { 3if (featureId == Window.FEATURE_ACTION_BAR && menu != null) { 4if (menu.getClass().getSimpleName().equals("MenuBuilder")) { 5try { 6 Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); 7 m.setAccessible(true); 8 m.invoke(menu, true); 9 } catch (Exception e) { 10 } 11 } 12 } 13returnsuper.onMenuOpened(featureId, menu); 14 }
可以看到,这里我们重写了一个onMenuOpened()方法,当overflow被展开的时候就会回调这个方法,接着在这个方法的内部通过返回反射的方法将MenuBuilder的setOptionalIconsVisible变量设置为true就可以了。
原文:http://www.cnblogs.com/liangstudyhome/p/3987241.html
内容总结
以上是互联网集市为您收集整理的【转】Android ActionBar完全解析,使用官方推荐的最佳导航栏(上)全部内容,希望文章能够帮你解决【转】Android ActionBar完全解析,使用官方推荐的最佳导航栏(上)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。