官方API
menu-resource
在Android中,菜单被分为如下三种,选项菜单(OptionsMenu)、上下文菜单(ContextMenu)和子菜单(SubMenu)
public boolean onCreateOptionsMenu(Menu menu)
:调用OptionMenu,在这里完成菜单初始化,只会在第一次初始化菜单时调用public boolean onOptionsItemSelected(MenuItem item)
:菜单项被选中时触发,这里完成事件处理当然除了上面这两个方法我们可以重写外我们还可以重写这三个方法:
public void onOptionsMenuClosed(Menu menu)
:菜单关闭会调用该方法public boolean onPrepareOptionsMenu(Menu menu)
:选项菜单显示前会调用该方法, 可在这里进行菜单的调整(动态加载菜单列表)public boolean onMenuOpened(int featureId, Menu menu)
:选项菜单打开以后会调用这个方法加载菜单的方式有两种,
一种是直接通过编写菜单XML文件,然后调用: getMenuInflater().inflate(R.menu.XXXX, menu)
;加载菜单
或者通过代码动态添加,onCreateOptionsMenu的参数menu,调用add方法添加 菜单,add(菜单项的组号,ID,排序号,标题),另外如果排序号是按添加顺序排序的话都填0即可!
package com.turing.base.activity.menu;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import com.turing.base.R;
/** * 最常用的就是选项菜单(optionsMenu), * 该菜单在点击 menu 按键 后会在对应的Activity底部显示出来。(4.4以前) * Activity菜单机制 ,Activity有一套机制来实现对菜单的管理 就是下面重写的几个方法 */
public class OPtionMenuDemoAct extends AppCompatActivity {
private TextView textView;
//1.定义不同颜色的菜单项的标识:
final private int RED = 110;
final private int GREEN = 111;
final private int BLUE = 112;
final private int YELLOW = 113;
final private int GRAY= 114;
final private int CYAN= 115;
final private int BLACK= 116;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_option_menu_demo);
textView = (TextView) findViewById(R.id.id_tv_optionMenuText);
}
/** * 两种方式 1.通过menu的xml加载,2 通过代码动态创建 * * @param menu * @return */
@Override
public boolean onCreateOptionsMenu(Menu menu) {
/** * 此方法用于初始化菜单,其中menu参数就是即将要显示的Menu实例。 返回true则显示该menu,false 则不显示; * (只会在第一次初始化菜单时调用) * Inflate the menu; this adds items to the action bar if it is present. */
/** * 通过xml加载菜单 * getMenuInflater().inflate(R.menu.options_menu, menu); 调用Activity的getMenuInflater()得到一个MenuInflater, 使用inflate方法来把布局文件中的定义的菜单 加载给 第二个参数所对应的menu对象 如果需要设置图片,可以在xml中设置 android:icon="@drawable/setting" 高版本的SDK,即使设置了 Icon,也不会显示的。低版本的会显示 */
//getMenuInflater().inflate(R.menu.menu_main,menu);
/** * * 第二种方式: 通过代码动态创建 * * menu.add((int groupId, int itemId, int order, charsequence title) .setIcon(drawable ID) add()方法的四个参数,依次是: 1、组别,如果不分组的话就写Menu.NONE, 2、Id,这个很重要,Android根据这个Id来确定不同的菜单 3、顺序,哪个菜单项在前面由这个参数的大小决定 4、文本,菜单项的显示文本 add()方法返回的是MenuItem对象,调用其setIcon()方法,为相应MenuItem设置Icon 高版本的SDK,即使设置了 Icon,也不会显示的。2.3低版本的会显示 */
// 高版本的SDK,即使设置了 Icon,也不会显示的。低版本的会显示
menu.add(1,RED,4,"红色").setIcon(R.drawable.flag_mark_red);
menu.add(1,GREEN,2,"绿色").setIcon(R.drawable.flag_mark_green);
menu.add(1,BLUE,3,"蓝色").setIcon(R.drawable.flag_mark_blue);
menu.add(1,YELLOW,1,"黄色").setIcon(R.drawable.flag_mark_yellow);
menu.add(1,GRAY,5,"灰色").setIcon(R.drawable.flag_mark_gray);
menu.add(1,CYAN,6,"蓝绿色").setIcon(R.drawable.gur_project_10);
menu.add(1,BLACK,7,"黑色").setIcon(R.drawable.gur_project_5);
// 返回true则显示该menu,false 则不显示;
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
/** * 在onCreateOptionsMenu执行后,菜单被显示前调用; * 如果菜单已经被创建,则在菜单显示前被调用。 * 同样的,返回true则显示该menu,false 则不显示; * (可以通过此方法动态的改变菜单的状态,比如加载不同的菜单等) */
return super.onPrepareOptionsMenu(menu);
}
@Override
public void onOptionsMenuClosed(Menu menu) {
/** * 每次菜单被关闭时调用. * (菜单被关闭有三种情形,menu按钮被再次点击、back按钮被点击或者用户选择了某一个菜单项) */
super.onOptionsMenuClosed(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
/** * 菜单项被点击时调用,也就是菜单项的监听方法。 * 通过这几个方法,可以得知,对于Activity,同一时间只能显示和监听一个Menu 对象。 */
switch ( item.getItemId()){
case RED: //对应的ID就是在add方法中所设定的Id
textView.setTextColor(Color.RED);
break;
case GREEN:
textView.setTextColor(Color.GREEN);
break;
case BLUE:
textView.setTextColor(Color.BLUE);
break;
case YELLOW:
textView.setTextColor(Color.YELLOW);
break;
case GRAY:
textView.setTextColor(Color.GRAY);
break;
case CYAN:
textView.setTextColor(Color.CYAN);
break;
case BLACK:
textView.setTextColor(Color.BLACK);
break;
}
/** * 如果是通过xml加载的菜单选项,那么Id就是布局文件中定义的Id,在用R.id.XXX的方法获取出来 */
return super.onOptionsItemSelected(item);
}
}
在Android 3.0或者更高的版本,则是通过3.0引入的ActionBar中的setting菜单:
在5.0以上的版本则是在ToolBar中的,点击后出一个溢出式的菜单样式
长按某个View后出现的菜单,我们需要为这个View注册上下文菜单!
onCreateContextMenu()
方法registerForContextMenu()
方法,参数是ViewonContextItemSelected()
方法为菜单项指定事件监听器在这里我们通过xml来加载,当然了也可以用代码创建~
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 定义一组单选按钮 -->
<!-- checkableBehavior的可选值由三个: single设置为单选, all为多选,none为普通选项 -->
<group android:checkableBehavior="none">
<item android:id="@+id/op1" android:title="选项一" />
<item android:id="@+id/op2" android:title="选项二" />
<item android:id="@+id/op3" android:title="选项三" />
</group>
</menu>
package com.turing.base.activity.menu;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import com.turing.base.R;
import java.util.ArrayList;
import java.util.List;
/** * 长按某个View后出现的菜单,我们需要为这个View注册上下文菜单! * <p/> * 使用的流程如下: * Step 1:重写onCreateContextMenu()方法 * Step 2:为view组件注册上下文菜单,使用registerForContextMenu()方法,参数是View * Step 3:重写onContextItemSelected()方法为菜单项指定事件监听器 * * * * 上下文菜单无法显示图标! */
public class ContextMenuDemoAct extends AppCompatActivity {
private ListView listView;
private List dataList = new ArrayList();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_context_menu_demo);
listView = (ListView) findViewById(R.id.id_listView);
for (int i = 0; i < 20; i++) {
dataList.add(i);
}
ArrayAdapter adapter = new ArrayAdapter(ContextMenuDemoAct.this,
android.R.layout.simple_list_item_1, dataList);
listView.setAdapter(adapter);
registerForContextMenu(listView);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(ContextMenuDemoAct.this, "onItemClick", Toast.LENGTH_SHORT).show();
}
});
}
//重写上下文菜单的创建方法
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
getMenuInflater().inflate(R.menu.menu_context,menu);
super.onCreateContextMenu(menu, v, menuInfo);
}
//上下文菜单被点击是触发该方法
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.op1:
Toast.makeText(this,"op1",Toast.LENGTH_SHORT).show();
break;
case R.id.op2:
Toast.makeText(this,"op2",Toast.LENGTH_SHORT).show();
break;
case R.id.op3:
Toast.makeText(this,"op3",Toast.LENGTH_SHORT).show();
break;
}
return true;
}
}
所谓的子菜单只是在<item>中又嵌套了一层<menu>,仅此而已。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/submenu" android:title="子菜单使用演示~">
<menu>
<group android:checkableBehavior="none">
<item android:id="@+id/one" android:title="子菜单一" />
<item android:id="@+id/two" android:title="子菜单二" />
<item android:id="@+id/three" android:title="子菜单三" />
</group>
</menu>
</item>
</menu>
package com.turing.base.activity.menu;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.turing.base.R;
/** * 所谓的子菜单只是在<**item**>中又嵌套了一层<**menu**>而已 * <p/> * 在Java代码中添加子菜单的话,可以调用addSubMenu() * 比如:SubMenu file = menu.addSubMenu("文件");file还需要addItem添加菜单项! */
public class SubMenuDemoAct extends AppCompatActivity {
private TextView textView ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sub_menu_demo);
textView = (TextView) findViewById(R.id.id_tv_info);
registerForContextMenu(textView);
}
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo) {
//子菜单部分:
MenuInflater inflator = new MenuInflater(this);
inflator.inflate(R.menu.menu_sub, menu);
super.onCreateContextMenu(menu, v, menuInfo);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.one:
Toast.makeText(SubMenuDemoAct.this, "你点击了子菜单一", Toast.LENGTH_SHORT).show();
break;
case R.id.two:
item.setCheckable(true);
Toast.makeText(SubMenuDemoAct.this, "你点击了子菜单二", Toast.LENGTH_SHORT).show();
break;
case R.id.three:
Toast.makeText(SubMenuDemoAct.this, "你点击了子菜单三", Toast.LENGTH_SHORT).show();
item.setCheckable(true);
break;
}
return true;
}
}
一个类似于PopupWindow的控件,他可以很方便的在指定View下显示一个弹出菜单,而且 他的菜单选项可以来自于Menu资源。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/see" android:title="查看" />
<item android:id="@+id/download" android:title="下载" />
</menu>
package com.turing.base.activity.menu;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.PopupMenu;
import android.view.Gravity;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import com.turing.base.R;
public class PopupMenuDemoAct extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_popup_menu_demo);
}
public void showPopupMenu(View view ){
// 初始化PopupMenu控件
PopupMenu popup = new PopupMenu(PopupMenuDemoAct.this,view);
// 加载菜单选项
popup.getMenuInflater().inflate(R.menu.menu_pop, popup.getMenu());
// 设置显示位置
popup.setGravity(Gravity.RIGHT);
// 设置监听事件
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()){
case R.id.see:
Toast.makeText(PopupMenuDemoAct.this, "查看",
Toast.LENGTH_SHORT).show();
break;
case R.id.download:
Toast.makeText(PopupMenuDemoAct.this,"下载",
Toast.LENGTH_SHORT).show();
break;
}
return true;
}
});
// 显示PopupMenu控件
popup.show();
}
}
替换Android菜单实现自定义菜单风格
这里menuView是自定的菜单风格,是一个View。
最重要的是:onCreateOptionsMenu + onMenuOpened
/** * 创建MENU */
public boolean onCreateOptionsMenu(Menu menu) {
menu.add("menu");// 必须创建一项
return super.onCreateOptionsMenu(menu);
}
/** * 拦截MENU事件,显示自己的菜单 */
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
if (menuDialog == null) {
menuDialog = new AlertDialog.Builder(this).setView(menuView).show();
} else {
menuDialog.show();
}
return false;// 返回为true 则显示系统menu
}
package com.turing.base.activity.menu;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.SimpleAdapter;
import com.turing.base.R;
import java.util.ArrayList;
import java.util.HashMap;
public class CustomizeMenu extends AppCompatActivity {
private boolean isMore = false;// menu菜单翻页控制
AlertDialog menuDialog;// menu菜单Dialog
GridView menuGrid;
View menuView;
private final int ITEM_SEARCH = 0;// 搜索
private final int ITEM_FILE_MANAGER = 1;// 文件管理
private final int ITEM_DOWN_MANAGER = 2;// 下载管理
private final int ITEM_FULLSCREEN = 3;// 全屏
private final int ITEM_MORE = 11;// 菜单
/** * 菜单图片 **/
int[] menu_image_array = {
R.drawable.menu_search,
R.drawable.menu_filemanager, R.drawable.menu_downmanager,
R.drawable.menu_fullscreen, R.drawable.menu_inputurl,
R.drawable.menu_bookmark, R.drawable.menu_bookmark_sync_import,
R.drawable.menu_sharepage, R.drawable.menu_quit,
R.drawable.menu_nightmode, R.drawable.menu_refresh,
R.drawable.menu_more};
/** * 菜单文字 **/
String[] menu_name_array = {
"搜索", "文件管理", "下载管理", "全屏", "网址", "书签",
"加入书签", "分享页面", "退出", "夜间模式", "刷新", "更多"};
/** * 菜单图片2 **/
int[] menu_image_array2 = {
R.drawable.menu_auto_landscape,
R.drawable.menu_penselectmodel, R.drawable.menu_page_attr,
R.drawable.menu_novel_mode, R.drawable.menu_page_updown,
R.drawable.menu_checkupdate, R.drawable.menu_checknet,
R.drawable.menu_refreshtimer, R.drawable.menu_syssettings,
R.drawable.menu_help, R.drawable.menu_about, R.drawable.menu_return};
/** * 菜单文字2 **/
String[] menu_name_array2 = {
"自动横屏", "笔选模式", "阅读模式", "浏览模式", "快捷翻页",
"检查更新", "检查网络", "定时刷新", "设置", "帮助", "关于", "返回"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_customize_menu);
menuView = View.inflate(this, R.layout.gridview_menu, null);
// 创建AlertDialog
menuDialog = new AlertDialog.Builder(this).create();
menuDialog.setView(menuView);
menuDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
public boolean onKey(DialogInterface dialog, int keyCode,
KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU)// 监听按键
dialog.dismiss();
return false;
}
});
menuGrid = (GridView) menuView.findViewById(R.id.gridview);
menuGrid.setAdapter(getMenuAdapter(menu_name_array, menu_image_array));
/** 监听menu选项 **/
menuGrid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
switch (arg2) {
case ITEM_SEARCH:// 搜索
break;
case ITEM_FILE_MANAGER:// 文件管理
break;
case ITEM_DOWN_MANAGER:// 下载管理
break;
case ITEM_FULLSCREEN:// 全屏
break;
case ITEM_MORE:// 翻页
if (isMore) {
menuGrid.setAdapter(getMenuAdapter(menu_name_array2,
menu_image_array2));
isMore = false;
} else {// 首页
menuGrid.setAdapter(getMenuAdapter(menu_name_array,
menu_image_array));
isMore = true;
}
menuGrid.invalidate();// 更新menu
menuGrid.setSelection(ITEM_MORE);
break;
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// 必须创建一项,否则不显示...
menu.add("menu");
return super.onCreateOptionsMenu(menu);
}
private SimpleAdapter getMenuAdapter(String[] menuNameArray,
int[] imageResourceArray) {
ArrayList<HashMap<String, Object>> data = new ArrayList<HashMap<String, Object>>();
for (int i = 0; i < menuNameArray.length; i++) {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("itemImage", imageResourceArray[i]);
map.put("itemText", menuNameArray[i]);
data.add(map);
}
SimpleAdapter simperAdapter = new SimpleAdapter(this, data,
R.layout.item_menu, new String[]{"itemImage", "itemText"},
new int[]{R.id.item_image, R.id.item_text});
return simperAdapter;
}
/** * 自定义布局 * @param featureId * @param menu * @return */
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
if (menuDialog == null) {
menuDialog = new AlertDialog.Builder(this).setView(menuView).show();
} else {
menuDialog.show();
}
return false;// 返回为true 则显示系统menu
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" >
<GridView android:id="@+id/gridview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:numColumns="4" android:verticalSpacing="10dip" android:horizontalSpacing="10dip" android:stretchMode="columnWidth" android:gravity="center" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/RelativeLayout_Item" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingBottom="5dip">
<ImageView android:id="@+id/item_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:src="@drawable/menu_about"/>
<TextView android:id="@+id/item_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/item_image" android:layout_centerHorizontal="true" android:text="选项"></TextView>
</RelativeLayout>