什么是Alternative menu(替代菜单)
举个例子,Activity显示一个文本文件。如果用户想对文本文件进行编辑,Activity不提供编辑能力,但可由其他activity或者其他应用提供。我们将相关信息存储在一个intent中,例如该文本的Uri。这个intent可以匹配系统的多个应用,替代菜单将这些应用一一列出,菜单项的title就是该可被调用的activity的名字,图标也为该可被调用的activity的图表。
小例子说明
我们通过一个小例子进行学习,简单地打开一个URL:wei://flowingflying/helloworld。在之前Intent的学习中,我们通过schema的配置,匹配该URL,也就是我们已经有其他应用的Activity(Intent Basic Test)可以打开该URL。我们同时在App中新增一个activity也能打开该URL。这样,将在alternative菜单中加入两个菜单项,点击它们,将打开相应的activity,并通过intent传递相关的数据信息。
新增的acitivity名字为Invoke Action(好像应该是invoked才对,不好意思)。在AndroidManifest.xml中加入intent-fliter的描述即可,具体见:Pro Android学习笔记(十一):了解Intent(中) 。
<activity android:name=".InvokeAction" android:label="@string/invokeAction" android:icon="@drawable/leaf" >
<intent-filter >
<action android:name="android.intent.action.VIEW" />
<data android:scheme="wei" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.ALTERNATIVE" /><!-- 将在最后讨论 -->
</intent-filter>
</activity>
Alternative menu代码
我们看看如何将替代菜单加入到OptionMenu中。Alternative menu还可以加载subMenu,Context Menu中。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// 对比:加入一个普通菜单项
menu.add("普通菜单项");
//【步骤1】设置intent,本例简单实用一个已知的Uri。
Intent menuIntent = new Intent(null,Uri.parse("wei://flowingflying/helloWorld"));
//【步骤2】加入Alternative菜单。在之前的Item ID类别中已经讲过,Android对ID进行了划分,有alternative的ID范围。
int menuGroup = Menu.CATEGORY_ALTERNATIVE;
int startingItemId = Menu.CATEGORY_ALTERNATIVE;
int orderId = Menu.CATEGORY_ALTERNATIVE;
menu.addIntentOptions( //返回增加的菜单项数目,本例为2
menuGroup, /* int groupId */
startingItemId, /* int itemId:由于自动跳转到,此参数可以设置为Menu.NONE。 */
orderId, /*int order*/
this.getComponentName(), /* ComponentName caller:当前的activity名字,这是android系统处理alternatice menu是调用的queryIntentActivityOptions()函数所需要的参数。getComponentName()返回package名字和class名字,系统以此获知源activity是谁。 */
null, /* Intent[] specifics:匹配可能有多个intent,此用于过滤,但具体用途不详 */
menuIntent, /* Intent intent:关键的intent */
0, /* flages:关于items如何加入。0表示 no flag*/
null); /* MenuItem[] outSpecificItems ,与specifice相关*/
return super.onCreateOptionsMenu(menu);
}
关于Category和规范代码写法
我们注意到,在被唤起的actvity中有下面的描述:
- <category android:name="android.intent.category.ALTERNATIVE" />
在试验中,发现此项可有可无,并不真正影响结果。而在reference中却明确表示要为CATEGORY_ALTERNATIVE或者CATEGORY_SELECTED_ALTERNATIVE。为何?
我们以Alternative menu的方式调用其他activity,正规的做法是,被唤起的activity应允许被alternative菜单唤起。因此被唤起的activity在intent-fliter中需给出类别。同时alternative菜单的intent也应当标明自己类型。因此规范的代码是:
Intent menuIntent = new Intent(null,this.getIntent().getData());
menuIntent.addCategory(Intent.CATEGORY_ALTERNATIVE);
在小例子中,由于其他应用的Activity(Intent Basic Test)在Manifest XML中并没有给出相应的类别,不被匹配。运行结果如图:
关于flags
menu.addIntentOptions()的倒数第二个参数是flags,表示菜单项添加的方式。0,即缺省,表示如果groupId相同,则替代菜单将取代原有的菜单项设置。如果我们想保留原有的同一Group的菜单项,可以将flags设置为Menu.FLAG_APPEND_TO_GROUP。注意,如果groupId为Menu.NONE是不进行替换的,这个表示不设置GroupId,并非GroupId为0。
多个匹配的itemId等参数
让我们看看系统是如何实现Alternative菜单的。从reference中看到,Menu是一个interface,具体是通过MenuBuilder实现(源代码见android-17(version)/com/android/internal/view/menu/MenuBuilder.java。相关代码如下:
public int addIntentOptions(int group, int id, int categoryOrder, ComponentName caller,
Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) {
PackageManager pm = mContext.getPackageManager();
final List<ResolveInfo> lri = //查询匹配的Activity信息
pm.queryIntentActivityOptions(caller, specifics, intent, 0);
final int N = lri != null ? lri.size() : 0;
//下面说明如果flag表示FLAG_APPEND_TO_GROUP,会删除整个group,取而代之
if ((flags & FLAG_APPEND_TO_GROUP) == 0) {
removeGroup(group);
}
for (int i=0; i<N; i++) {
final ResolveInfo ri = lri.get(i);
Intent rintent = new Intent(
ri.specificIndex < 0 ? intent : specifics[ri.specificIndex]);
rintent.setComponent(new ComponentName(
ri.activityInfo.applicationInfo.packageName,
ri.activityInfo.name));
final MenuItem item = add(group, id, categoryOrder, ri.loadLabel(pm))
.setIcon(ri.loadIcon(pm))
.setIntent(rintent);
if (outSpecificItems != null && ri.specificIndex >= 0) {
outSpecificItems[ri.specificIndex] = item;
}
}
return N;
}
从源代码,可能看出如果有多个匹配,这些菜单项具有相同的group,相同的id,和相同categoryOrder。虽然我们在小例子中使用了startingItemId,但是实际上itemId是相同的。在小例子中,我们增加了public boolean onOptionsItemSelected(MenuItem item),并在里面检查item的参数值,证实确实相同。
这段代码还说明了菜单项的名字和图片为何,以及为何能唤起Activity。采用了setIntent(),是在Pro Android学习笔记(三十):Menu(1):了解Menu学习过的的一种触发机制。
本博文涉及的例子代码,可以在Pro Android学习:Menu中下载。
相关链接: 我的Android开发相关文章
【转】 Pro Android学习笔记(三三):Menu(4):Alternative菜单的更多相关文章
-
【转】 Pro Android学习笔记(三五):Menu(6):XML方式 &; PopUp菜单
目录(?)[-] 利用XML创建菜单 XML的有关属性 onClick事件 Pop-up菜单 利用XML创建菜单 在代码中对每个菜单项进行设置,繁琐且修改不灵活,不能适配多国语言的要求,可以利用资源进 ...
-
【转】Pro Android学习笔记(三十):Menu(1):了解Menu
目录(?)[-] 创建Menu MenuItem的属性itemId MenuItem的属性groupId MenuItem的属性orderId MenuItem的属性可选属性 Menu触发 onOpt ...
-
Pro Android学习笔记 ActionBar(1):Home图标区
Pro Android学习笔记(四八):ActionBar(1):Home图标区 2013年03月10日 ⁄ 综合 ⁄ 共 3256字 ⁄ 字号 小 中 大 ⁄ 评论关闭 ActionBar在A ...
-
【转】 Pro Android学习笔记(八二):了解Package(1):包和进程
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 在之前,我们已经学习了如何签发apk,见P ...
-
【转】 Pro Android学习笔记(六七):HTTP服务(1):HTTP GET
目录(?)[-] HTTP GET小例子 简单小例子 出现异常NetworkOnMainThreadException 通过StrictMode进行处理 URL带键值对 Andriod应用可利用ser ...
-
【转】 Pro Android学习笔记(五五):调试和分析(3):adb命令、模拟器控制台和StrictMode
目录(?)[-] adb命令 模拟器Console StrictMode adb命令 我们在学习SQLite的使用,介绍过部分adb命令的使用,见Pro Android学习笔记(五):了解Conten ...
-
【转】 Pro Android学习笔记(五六):配置变化
目录(?)[-] Activity的destorycreate过程 Fragment的destorycreate过程 onSaveInstanceState saveFragmentInstanceS ...
-
【转】 Pro Android学习笔记(五二):ActionBar(5):list模式
可以在action bar中加入spinner的下来菜单,有关spinner,可以参考Pro Android学习笔记(二十):用户界面和控制(8):GridView和Spinner. list的样式和 ...
-
【转】 Pro Android学习笔记(四二):Fragment(7):切换效果
目录(?)[-] 利用setTransition 利用setCustomAnimations 通过ObjectAnimator自定义动态效果 程序代码的编写 利用fragment transactio ...
随机推荐
-
hibernate开发(1)
1 什么是ORM OR-mapping 是 object relational mapping 对象关系映射,是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换.解决了不同数据库s ...
-
Codeforces 730I [费用流]
/* 不要低头,不要放弃,不要气馁,不要慌张 题意: 给两行n个数,要求从第一行选取a个数,第二行选取b个数使得这些数加起来和最大. 限制条件是第一行选取了某个数的条件下,第二行不能选取对应位置的数. ...
-
Hadoop离线项目介绍(不包括程序)
一:项目场景 1.需求分析 根据用户行为数据进行程序的处理,得到结果保存到关系型数据库中 需要收集用户(系统使用者)在不同客户端上产生的用户行为数据,最终保存到hdfs上 需要明确收集字段的相关信息, ...
-
Scrum Meeting 1-20151201
任务安排 姓名 今日任务 明日任务 困难 董元财 学习下拉刷新的实现 完成下拉刷新的实现 手机的点击动作长按和下拉有类似的地方,比较难解决 胡亚坤 学习圆形头像代码设计 完成圆形头像代码设计 无 刘猛 ...
-
Linux命令(2)- mv
mv 功能:可以用来移动文件或者将文件改名. 格式:mv [选项] 源文件或目录 目标文件或目录 说明:mv命令将文件重命名或将其移至一个新的目录中.第二个参数类型是文件时,mv命令完成文件重命名,此 ...
-
[Effective Java]第二章 创建和销毁对象
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
-
java+hadoop+spark+hbase+scala+kafka+zookeeper配置环境变量记录备忘
java+hadoop+spark+hbase+scala 在/etc/profile 下面加上如下环境变量 export JAVA_HOME=/usr/java/jdk1.8.0_102 expor ...
-
.PIG File
.PIG File File extension: PIG File type: Texture File The PIG file type is primarily associated with ...
-
Javascript 闭包与变量
1.闭包与变量 JavaScript中的作用域链的机制引出了一个副作用,即闭包只能取得包含函数中任何变量的最后一个值.闭包所保存的是整个变量对象,而不是某个特殊的值. 1 2 3 4 5 6 7 8 ...
-
关于两栏布局,三栏布局,一级点击三角触发select的onchange事件问题
首先看这样一个效果:,这个截图来自移动端的列表的一整行,在这个效果当中,存在两个技术点,首先选择祝福卡这个宽度是一定的,右边的部分,宽度随着手机屏幕的宽度而自适应,再一个技术点就是点击最右侧向下箭头, ...