Android ActionBar全然解析,使用官方推荐的最佳导航栏(上)
转载请注明出处: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]是两个actionbutton,[3]是overflowbutton。
因为Action Bar是在3.0以后的版本号中加入的。假设想在2.x的版本号里使用ActionBar的话则须要引入Support Library,只是3.0之前版本号的市场占有率已经很小了,这里简单起见我们就不再考虑去做向下兼容,而是仅仅考虑4.0以上版本号的使用方法。
加入和移除Action Bar
ActionBar的加入很easy,仅仅须要在AndroidManifest.xml中指定Application或Activity的theme是Theme.Holo或其子类就能够了,而使用Eclipse创建的项目自己主动就会将Application的theme指定成Theme.Holo。所以ActionBar默认都是显示出来的。新建一个空项目并执行。效果例如以下图所看到的:
而假设想要移除ActionBar的话通常有两种方式。一是将theme指定成Theme.Holo.NoActionBar,表示使用一个不包括ActionBar的主题,二是在Activity中调用下面方法:
ActionBar actionBar = getActionBar();
actionBar.hide();
如今又一次执行一下程序,就能够看到ActionBar不再显示了,例如以下图所看到的:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2lueXU4OTA4MDc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
改动Action Bar的图标和标题
<activity
android:name="com.example.actionbartest.MainActivity"
android:logo="@drawable/weather" >
</activity>
如今又一次执行一下程序,效果例如以下图所看到的:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2lueXU4OTA4MDc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
<activity
android:name="com.example.actionbartest.MainActivity"
android:label="天气"
android:logo="@drawable/weather" >
</activity>
加入Actionbutton
当然,假设button过多,ActionBar上显示不完。多出的一些button能够隐藏在overflow里面(最右边的三个点就是overflowbutton)。点击一下overflowbutton就能够看到全部的Actionbutton了。
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.actionbartest.MainActivity" >
<item
android:id="@+id/action_compose"
android:icon="@drawable/ic_action_compose"
android:showAsAction="always"
android:title="@string/action_compose"/>
<item
android:id="@+id/action_delete"
android:icon="@drawable/ic_action_delete"
android:showAsAction="always"
android:title="@string/action_delete"/>
<item
android:id="@+id/action_settings"
android:icon="@drawable/ic_launcher"
android:showAsAction="never"
android:title="@string/action_settings"/>
</menu>
能够看到,这里我们通过三个<item>标签定义了三个Actionbutton。<item>标签中又有一些属性,其中id是该Actionbutton的唯一标识符。icon用于指定该button的图标,title用于指定该button可能显示的文字(在图标能显示的情况下,通常不会显示文字)。showAsAction则指定了该button显示的位置。主要有下面几种值可选:always表示永远显示在ActionBar中,假设屏幕空间不够则无法显示。ifRoom表示屏幕空间够的情况下显示在ActionBar中,不够的话就显示在overflow中,never则表示永远显示在overflow中。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
这部分代码很easy,仅仅是调用了MenuInflater的inflate()方法来载入menu资源就能够了。如今又一次执行一下程序,结果例如以下图所看到的:
- 当ActionBar中的剩余空间不足的时候,假设Actionbutton指定的showAsAction属性是ifRoom的话。该Actionbutton就会出如今overflow其中,此时就仅仅有title能够显示了。
- 假设Actionbutton在ActionBar中显示,用户可能通过长按该Actionbutton的方式来查看到title的内容。
响应Actionbutton的点击事件
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_compose:
Toast.makeText(this, "Compose", Toast.LENGTH_SHORT).show();
return true;
case R.id.action_delete:
Toast.makeText(this, "Delete", Toast.LENGTH_SHORT).show();
return true;
case R.id.action_settings:
Toast.makeText(this, "Settings", Toast.LENGTH_SHORT).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
能够看到,我们让每一个Actionbutton被点击的时候都弹出一个Toast,如今又一次执行一下代码。结果例如以下图所看到的:
通过Action Bar图标进行导航
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("天气");
setContentView(R.layout.activity_main);
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
}
如今又一次执行一下程序,结果例如以下图所看到的:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
……
}
}
当点击ActionBar图标的时候,系统相同会调用onOptionsItemSelected()方法。而且此时的itemId是android.R.id.home,所以finish()方法也就是加在这里的了。
没错,假设我们仅仅是简单地finish了一下。ActionBar导航和Back键的功能是全然一样的,但ActionBar导航的设计初衷并非这种,它和Back键的功能还是有一些差别的。举个样例吧。
而ActionBar导航则不应该表现出这种行为,不管我们当前在哪一个Conversation details界面。点击一下导航button都应该回到Conversation List界面才对。
<activity
android:name="com.example.actionbartest.MainActivity"
android:logo="@drawable/weather" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.actionbartest.LaunchActivity" />
</activity>
能够看到,这里通过meta-data标签指定了MainActivity的父Activity是LaunchActivity。在Android 4.1版本号之后,也能够直接使用android:parentActivityName这个属性来进行指定。例如以下所看到的:
<activity
android:name="com.example.actionbartest.MainActivity"
android:logo="@drawable/weather"
android:parentActivityName="com.example.actionbartest.LaunchActivity" >
</activity>
第三步则须要对android.R.id.home这个事件进行一些特殊处理。例如以下所看到的:
@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;
......
}
}
其中,调用NavUtils.getParentActivityIntent()方法能够获取到跳转至父Activity的Intent。然后假设父Activity和当前Activity是在同一个Task中的,则直接调用navigateUpTo()方法进行跳转,假设不是在同一个Task中的,则须要借助TaskStackBuilder来创建一个新的Task。
加入Action View
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<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" />
......
</menu>
注意在showAsAction属性中我们还声明了一个collapseActionView,这个值表示该控件能够被合并成一个Actionbutton。
@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);
}
在得到了SearchView的实例之后,就能够随意地配置它的各种属性了。关于SearchView的很多其他具体使用方法,能够參考官方文档 http://developer.android.com/guide/topics/search/search-dialog.html 。
@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操作就能够了。
Overflowbutton不显示的情况
比方我们启动一个有Menu键的模拟器。然后将代码执行到该模拟器上,结果例如以下图所看到的:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2lueXU4OTA4MDc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
那么此时我们怎样查看隐藏在overflow中的Actionbutton呢?事实上很easy,按一下Menu键,隐藏的内容就会从底部出来了,例如以下图所看到的:
@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();
}
}
这里我们在onCreate()方法的最后调用了setOverflowShowingAlways()方法,而这种方法的内部就是使用反射的方式将sHasPermanentMenuKey的值设置成false,如今又一次执行一下代码。结果例如以下图所看到的:
让Overflow中的选项显示图标
@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);
}
能够看到,这里我们重写了一个onMenuOpened()方法,当overflow被展开的时候就会回调这种方法,接着在这种方法的内部通过返回反射的方法将MenuBuilder的setOptionalIconsVisible变量设置为true就能够了。
关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。
微信扫一扫下方二维码就可以关注:
![]()
Android ActionBar全然解析,使用官方推荐的最佳导航栏(上)的更多相关文章
- Android ActionBar完全解析,使用官方推荐的最佳导航栏(上)
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/18234477 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工 ...
- 【转】Android ActionBar完全解析,使用官方推荐的最佳导航栏(上)
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/18234477 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工 ...
- Android ActionBar完全解析,使用官方推荐的最佳导航栏(下) .
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/25466665 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工 ...
- Android DiskLruCache全然解析,硬盘缓存的最佳方案
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/28863651 概述 记得在非常早之前.我有写过一篇文章Android高效载入大图. ...
- Android IntentService全然解析 当Service遇到Handler
转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/47143563: 本文出自:[张鸿洋的博客] 一 概述 大家都清楚.在Andro ...
- Android DiskLruCache完全解析,硬盘缓存的最佳方案
Android DiskLruCache完全解析,硬盘缓存的最佳方案 概述 记得在很早之前,我有写过一篇文章Android高效加载大图.多图解决方案,有效避免程序OOM,这篇文章是翻译自Andro ...
- Android Volley全然解析(四),带你从源代码的角度理解Volley
版权声明:本文出自郭霖的博客,转载必须注明出处. https://blog.csdn.net/sinyu890807/article/details/17656437 转载请注明出处:http://b ...
- 【Android - 自定义View】之自定义颜色渐变的Tab导航栏
首先来介绍一下这个自定义View: (1)这个自定义View的名称叫做 GradientTab ,继承自View类: (2)这个自定义View实现了颜色渐变的Tab导航栏(仿微信主菜单),用户在左右滑 ...
- Android ViewDragHelper全然解析 自己定义ViewGroup神器
转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/46858663. 本文出自:[张鸿洋的博客] 一.概述 在自己定义ViewGro ...
随机推荐
- MySQL事务笔记
1.结束事务的方法用什么? 2.事务的最终形态是什么? commit 提交 rollback 回滚 3.事务的四大特征? ⑴ 原子性 一个事务是最小的工作单元,事务包含的所有操作要么全部成功,要么全部 ...
- XCode - App installation failed (A valid provisioning profile for this executable was not found)
OSX:10.14 XCode:10.1 iPhone:iPhone 4S IOS9.3.5 我不得不骂那些SB们,不懂就别TMD乱写文章,误导别人!!我今天看了很多关于这个错误的中文文章,结果都没能 ...
- 哆啦A梦欺骗了你!浏览器CSS3测试遭质疑
首先,说明,此处只是告诫各位参与CSS3.0学习使用或者将要使用或者学习CSS3.0的朋友,不要完全信任网络资源,依靠网络资源,我们需要利用网络资源的方便和可取的部分,结合自己的理解,学好,理解好! ...
- php5.5之后新特性整理
1 生成器 yield关键字yield的中文文档在这里:http://php.net/manual/zh/language.generators.overview.php查看文档,能知道yield的一 ...
- Java基础——Ajax(一)
学习之前举一个简单的小栗子,让我们简单了解一下Ajax的应用与好处.一般网站都会有自己的数据库,用来单独存储用户的个人信息,平时我们在注册账号的时候会遇到信息输入的页面,假设第一个输入信息是用户名的填 ...
- Java-IO:复制文件
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStrea ...
- websocket学习和群聊实现
WebSocket协议可以实现前后端全双工通信,从而取代浪费资源的长轮询.在此协议的基础上,可以实现前后端数据.多端数据,真正的实时响应.在学习WebSocket的过程中,实现了一个简化版群聊,过程和 ...
- JS实现页面分享代码share,不需要第三方接口
在开发一个页面的时候常常会有这么一个小功能,就是分享该页面中的信息. 常见的分享代码有百度分享,JiaThis分享插件(现在貌似不能用了),bshare分享插件等,我主要分享一下自定义分享代码,如下: ...
- 2018-01-15 History in Threads: 火狐插件实现浏览历史按主题显示(树)
History in Threads似乎是唯一一个业余项目里有确认用户的. 大部分JavaScript源码(300+行)也用了中文命名. 插件功能很简单, 就是根据网页点击顺序生成树, 每个树可以认为 ...
- JavaScript与正则表达式
正则表达式的定义 正则表达式与字符串对象相关的方法 相关示例 一.正则表达式(regular expression简称res) 1.定义: 一个正则表达式就是由普通字符以及特殊字符(称为元字符)组成 ...