第五章 用户界面基础(菜单)

参考资料:
《Android应用程序开发》ISBN 9787302283164
参考软件:
Android Studio、Eclipse+ADT、Android SDK、JDK
菜单
应用程序中非常重要的组成部分
在不占用界面空间的前提下,为应用程序提供了统一的功能和设置界面
为程序开发人员提供了易于使用的编程接口
Android系统支持三种菜单
选项菜单(OptionMenu)
子菜单(Submenu)
快捷菜单(ContextMenu)
1、Android Studio下创建menu布局文件
http://www.cnblogs.com/ssqqhh/p/5213331.html
一、问题:
android studio项目中没有看到menu文件夹:

在android studio项目中想要添加menu布局文件,一开始我的做法是:直接在res文件夹右键选择xml文件来添加,如下图:

但是会发现新建的布局文件好像很奇怪,不能添加menu以及item,如下图:

二、解决办法:
经过百度才知道menu布局文件要在menu文件夹地下创建才行,正确的做法如下:
(1)先在res文件夹右键,然后如下图选择:

然后会出现下面的页面,在Resource type下拉栏选择menu,如下图:

最后点击OK就行了,这时候可以看到menu文件夹已经出来了;
(2)接着在menu文件夹下右键,选择如下:

输入文件名点击OK即可:

这样就可以了:

2、选项菜单
http://blog.csdn.net/jdsjlzx/article/details/36433441
http://blog.csdn.net/wwj_748/article/details/44588649
http://www.sjsjw.com/kf_mobile/article/039009ABA009108.asp
(1)强制ActionBar显示OverFlow按钮(三个点)
关于ActionBar最右这三个点按钮:

正式的名称应该是overflow menu,在android4.2.2以上的设备是默认出现的,但是android4.1.2的设备不显示,似乎android也没有提供显示的API,所以网上搜索到这个强制显示的方案(亲测可用)。
关键代码如下:
private void getOverflowMenu() {
ViewConfiguration viewConfig =ViewConfiguration.get(this);
try {
FieldoverflowMenuField =ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
if(null !=overflowMenuField){
overflowMenuField.setAccessible(true);
overflowMenuField.setBoolean(viewConfig,false);
}
} catch (NoSuchFieldExceptione) {
// TODO Auto-generatedcatch block
e.printStackTrace();
} catch(IllegalArgumentException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
} catch (IllegalAccessExceptione) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
在onCreate()的方法中直接调用就可以:
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated methodstub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_page);
……
//force to display overflowmenu in action bar
getOverflowMenu();
}
原作者有补充到即时应用于android4.4以上的设备应该也不会有问题:因为即使得到的overflowMenuField为null,代码也做了判空处理,所以没什么影响。
我实际在调用时加入版本兼容条件,如下:
//forceto display overflow menu in action bar when sdk version less than 21
if((Build.VERSION.SDK_INT >=10) & (Build.VERSION.SDK_INT < 21)) {
getOverflowMenu();
}
(2)代码实现

在代码中之间实现菜单

事件实现

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// getMenuInflater().inflate(R.menu.activity_main, menu);
// 使用java代码实现菜单
MenuItem menuItem = menu.add(1001, 100, 1, "系统菜单");
// menuItem.setIcon(R.drawable.ic_launcher);
menuItem.setTitle("菜单一");
MenuItem menuItem2 = menu.add(1001, 101, 2, "用户菜单");
menuItem2.setTitle("菜单二");// 最多可以显示6个子菜单
MenuItem menuItem3 = menu.add(1001, 102, 2, "客户菜单");
menuItem3.setTitle("菜单三");// 最多可以显示6个子菜单
menuItem3.setShortcut('c', 'c');// 给指定的菜单设置快捷键
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case 100:
Intent intent = new Intent(MainActivity.this, NextActivity.class);
item.setIntent(intent);
// item.setIntent(intent);
// Toast.makeText(MainActivity.this, "选择了菜单一", 1).show();
break;
case 101:
Toast.makeText(MainActivity.this, "选择了菜单二", 1).show();
break;
case 102:
Toast.makeText(MainActivity.this, "选择了菜单三", 1).show();
break;
}
return super.onOptionsItemSelected(item);
}
(3)资源文件实现


建立菜单的资源文件

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/menu_settings"
android:icon="@drawable/sys"
android:orderInCategory="100"
android:showAsAction="ifRoom|withText"
android:title="@string/menu_settings">
<menu>
<item
android:id="@+id/create_new"
android:title="新建文件">
</item>
<item
android:id="@+id/open"
android:title="打开文件"/>
</menu>
</item>
<item
android:id="@+id/sys"
android:icon="@drawable/sys"
android:orderInCategory="101"
android:showAsAction="never"
android:title="用户菜单">
<menu>
<group android:id="@+id/group1" >
<item
android:id="@+id/load"
android:title="加载文件">
</item>
</group>
<group android:id="@+id/group2" >
<item
android:id="@+id/save"
android:title="保存文件">
</item>
</group>
</menu>
</item>
</menu>
代码中的实现

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}

@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.create_new:
Intent intent = new Intent(MainActivity.this, SystemMenu.class);
item.setIntent(intent);
break;
case R.id.open:
Toast.makeText(MainActivity.this, "打开菜单", 1).show();
break;
case R.id.load:
Toast.makeText(MainActivity.this, "加载菜单", 1).show();
break;
case R.id.save:
Toast.makeText(MainActivity.this, "保存菜单", 1).show();
break;
}
return super.onMenuItemSelected(featureId, item);
}
(4) android:showAsAction

3、子菜单
子菜单就是二级菜单,点击选项菜单或快捷菜单中的菜单项,就可以打开子菜单
Android系统使用浮动窗体的形式显示菜单子项,可以更好适应小屏幕的显示方式

(1)资源文件实现


@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.sub_menu, menu);
return true;
}
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/main_menu_0"
android:icon="@drawable/pic0"
android:title="设置" >
<menu>
<item android:id="@+id/sub_menu_0_0"
android:icon="@drawable/pic4"
android:title="打印" />
</menu>
</item>
<item android:id="@+id/main_menu_1"
android:icon="@drawable/pic1"
android:title="新建" >
<menu>
<item android:id="@+id/sub_menu_1_0"
android:icon="@drawable/pic2"
android:title="邮件" />
<item android:id="@+id/sub_menu_1_1"
android:icon="@drawable/pic3"
android:title="订阅" />
</menu>
</item>
</menu>
(2)代码实现
package edu.hrbeu.SubMenu2;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.widget.TextView;
public class SubMenu2Activity extends Activity {
final static int MENU_00 = Menu.FIRST;
final static int MENU_01 = Menu.FIRST+1;
final static int SUB_MENU_00_01 = Menu.FIRST+2;
final static int SUB_MENU_01_00 = Menu.FIRST+3;
final static int SUB_MENU_01_01 = Menu.FIRST+4;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
SubMenu sub1 = (SubMenu) menu.addSubMenu(0,MENU_00,0,"设置")
.setHeaderIcon(R.drawable.pic3);
sub1.add(0,SUB_MENU_00_01 ,0,"打印").setIcon(R.drawable.pic0);
SubMenu sub2 = (SubMenu) menu.addSubMenu(0,MENU_01,1,"新建")
.setHeaderIcon(R.drawable.pic1);
sub2.add(0,SUB_MENU_01_00 ,0,"邮件").setIcon(R.drawable.pic2);
sub2.add(0,SUB_MENU_01_01 ,0,"订阅").setIcon(R.drawable.pic4);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
TextView label = (TextView)findViewById(R.id.label);
switch (item.getItemId()) {
case MENU_00:
label.setText("设置,菜单ID:" + item.getItemId());
return true;
case MENU_01:
label.setText("新建,菜单ID:" + item.getItemId());
return true;
case SUB_MENU_00_01:
label.setText("打印,子菜单ID:" + item.getItemId());
return true;
case SUB_MENU_01_00:
label.setText("邮件,子菜单ID:" + item.getItemId());
return true;
case SUB_MENU_01_01:
label.setText("订阅,子菜单ID:" + item.getItemId());
return true;
default:
return false;
}
}
}
4、上下文菜单(快捷菜单)
当用户点击界面元素超过2秒后,将启动注册到该界面元素的快捷菜单
类似于计算机程序中的“右键菜单”
与“选项菜单”的方法非常相似,需要重载:
onCreateContextMenu()函数
onContextItemSelected()函数
快捷菜单注册到界面中的某个控件上
registerForContextMenu()函数

例子

(1)资源文件

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/edit"
android:orderInCategory="100"
android:showAsAction="never"
android:title="Edit"/>
<item
android:id="@+id/share"
android:orderInCategory="100"
android:showAsAction="never"
android:title="Share"/>
<item
android:id="@+id/delete"
android:orderInCategory="100"
android:showAsAction="never"
android:title="Delete"/>
</menu>
(2)listview内容填充

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) this.findViewById(R.id.listView1);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, getData());
listView.setAdapter(adapter);
//给ListView注册上下文菜单
registerForContextMenu(listView);//View类型
}
public List<String> getData() {
List<String> list = new ArrayList<String>();
for (int i = 1; i <= 7; i++) {
list.add("jack" + i);
}
return list;
}
(3)下文菜单及事件

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
// 加载xml中的上下文菜单
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.activity_main, menu);
}
//响应上下文菜单的操作
@Override
public boolean onContextItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.delete:
Toast.makeText(MainActivity.this, "Delete", 1).show();
break;
case R.id.share:
Toast.makeText(MainActivity.this, "Share", 1).show();
break;
case R.id.edit:
Toast.makeText(MainActivity.this, "Edit", 1).show();
break;
}
return super.onContextItemSelected(item);
}
5、ActionModel菜单和PopUp菜单


(1)资源文件

<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/edit"
android:title="Edit"
android:orderInCategory="100"
android:showAsAction="never" />
<item android:id="@+id/share"
android:title="Share"
android:orderInCategory="100"
android:showAsAction="never" />
<item android:id="@+id/delete"
android:title="Share"
android:orderInCategory="100"
android:showAsAction="never" />
</menu>
(2)界面布局

<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:text="ActionModel" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/button1"
android:layout_below="@+id/button1"
android:layout_marginTop="67dp"
android:text="Popup" />
(3)代码实现
package com.example.android_menu_action_mode_popup;
import android.app.Activity;
import android.os.Bundle;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.widget.Button;
import android.widget.PopupMenu;
import android.widget.PopupMenu.OnMenuItemClickListener;
import android.widget.Toast;
public class MainActivity extends Activity {
private Button button;
private ActionMode actionMode;// 使用ActionMode完成菜单操作
private Button button2;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) this.findViewById(R.id.button1);
button.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
if (actionMode != null) {
return false;
}
actionMode = startActionMode(actionCallback);
v.setSelected(true);
return true;
}
});
button2 = (Button)this.findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
PopupMenu popupMenu = new PopupMenu(MainActivity.this, v);
popupMenu.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.edit:
edit();
break;
case R.id.delete:
Toast.makeText(MainActivity.this, "Delete", 1).show();
break;
case R.id.share:
Toast.makeText(MainActivity.this, "Share", 1).show();
break;
}
return false;
}
});
MenuInflater inflater = popupMenu.getMenuInflater();
inflater.inflate(R.menu.activity_main, popupMenu.getMenu());
popupMenu.show();//显示菜单
}
});
}
private ActionMode.Callback actionCallback = new ActionMode.Callback() {
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
// TODO Auto-generated method stub
actionMode = null;
}
// 表示我们要加载菜单,从xml中加载
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.activity_main, menu);
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.edit:
edit();
break;
case R.id.delete:
Toast.makeText(MainActivity.this, "Delete", 1).show();
break;
case R.id.share:
Toast.makeText(MainActivity.this, "Share", 1).show();
break;
}
return false;
}
};
public void edit() {
Toast.makeText(MainActivity.this, "Edit", 1).show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}