菜单的基本使用
在Android中,菜单被分为如下三种,选项菜单(OptionsMenu)、上下文菜单(ContextMenu)和子菜单(SubMenu)
OptionsMenu
效果图
说明
重写两个方法 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即可!
Code
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中的,点击后出一个溢出式的菜单样式
ContextMenu
效果图
说明
长按某个View后出现的菜单,我们需要为这个View注册上下文菜单!
操作步骤
Step 1:重写onCreateContextMenu()方法
Step 2:为view组件注册上下文菜单,使用 - registerForContextMenu()方法,参数是View
Step 3:重写onContextItemSelected()方法为菜单项指定事件监听器
在这里我们通过xml来加载,当然了也可以用代码创建~
Code
res\menu\menu_context.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>
ContextMenuDemoAct.java
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; } }
SubMenu
效果图
说明
所谓的子菜单只是在<item>中又嵌套了一层<menu>,仅此而已。
Code
menu_sub.xml
<?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>
SubMenuDemoAct.java
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; } }
PopupMenu
效果图
说明
一个类似于PopupWindow的控件,他可以很方便的在指定View下显示一个弹出菜单,而且 他的菜单选项可以来自于Menu资源。
Code
menu_pop.xml
<?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>
PopupMenuDemoAct.java
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 }
Code
CustomizeMenu.java
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 } }
gridview_menu.xml
<?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>
item_menu.xml
<?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>