zoukankan      html  css  js  c++  java
  • Android--Menus

    前言

      本篇博客讲解一下菜单Menu的使用。菜单在windows应用中使用十分广泛,几乎所有的windows应用都有菜单,Android中也加入了菜单的支持。从官方文档了解到,从Android3.0(API level 11)开始,Android设备不再要求提供一个专门的菜单按钮,转而推荐使用ActionBar。所以现在市面上很多新设备使用三个虚拟按键,并不再额外提供菜单按钮,但是按钮的使用也是有些地方可以借鉴的。

      因为Android版本的发展,对于菜单的支持各个版本有很大的区别,而Android3.0是个分水岭,大概可以分为下面三类:

    • OptionMenu和ActionBar:一些操作的集合,如果开发的平台在Android3.0之上,推荐使用ActionBar,如果开发的平台在Android2.3或之下,还是可以使用OptionMenu的。
    • ContextMenu和ActionMode:ContextMenu是一个浮动的窗口形式展现一个选项列表,ActionMode是一个显示在屏幕顶部的操作栏,允许用户选择多个选项,ActionMode在Android3.0之后才有支持。
    • Pupop Menu:PopupMenu是固定在View上的模态菜单,以弹出的方式显示,在Android3.0之后才有支持。

      

    在XML中定义一个菜单

      Android提供了标准的XML格式的资源文件来定义菜单项,并且对所有菜单类型都支持,推荐使用XML资源文件来定义菜单,之后再把它Inflater到Activity或者Fragment中,而不是在Activity中使用代码声明。

      而菜单的XML资源文件,需要创建在/res/menu/目录下,并且包含一下几个元素:

    • <menu>:定义一个Menu,是一个菜单资源文件的根节点,里面可以包含一个或者多个<item>和<group>元素。
    • <item>:创建一个MenuItem,代表了菜单中一个选项。
    • <group>:对菜单项进行分组,可以以组的形式操作菜单项。

      <item>元素除了常规的id、icon、title属性的支持,还有一个重要的属性:android:showAsAction,这个属性是起兼容性的,描述了在Android的高版本中,菜单项何时以何种方式加入到ActionBar中。

      <group>是对菜单进行分组,分组后的菜单显示效果并没有区别,唯一的区别在于可以针对菜单组进行操作,这样对于分类的菜单项,操作起来更方便,提供如下的操作:

    • Menu.setGroupCheckable():菜单组内的菜单是否都可选。
    • Menu.setGroupVisible():是否隐藏菜单组的所有菜单。
    • Menu.setGroupEnabled():菜单组的菜单是否有用。

      如果菜单项需要单选或者多选,可以使用android:checkableBehavior属性设置,它可以对单个<item>或者<group>设置一个组,这个属性接受三个参数:single,单选;all,多选,none,没有Checked的选项,默认。

      当创建好一个XML菜单资源文件之后,可以使用MenuInflater.inflate()方法填充菜单资源,使XML资源变成一个可编程的对象。

    OptionMenu

      OptionMenu,选项菜单,必须设备具有菜单按钮才可以触发。因为屏幕的限制,最多只能展示六个菜单项,如果定义的菜单项超出了六个,其他的菜单项将被隐藏,第六个菜单将会显示“更多”,点击展开更多的菜单。虽说在Android3.0之后不再推荐使用选项菜单,但是如果使用了,在Android3.0之后的设备上,选项菜单项将被默认转移到ActionBar中,这个可以通过android:showAsAction属性控制。

      使用OptionMenu需要在Activity或者Fragment中重写onCreateOptionsMenu(Menu)方法,在这个方法中声明一个选项菜单。菜单的存在是为了提供操作,所以Activity和Fragment中还提供了一个onOptionsItemSelected(MenuItem)方法,用于响应选项菜单中选中的时候的响应。OptionMenu就是操作一个Menu对象和MenuItem对象。

      下面通过两个Demo来展示一段选项菜单的使用,分别使用代码声明菜单和XML资源文件声明菜单的方式说明。

      声明代码: 

    复制代码
     1 package com.example.menudemo;
     2 
     3 import android.app.Activity;
     4 import android.content.Intent;
     5 import android.os.Bundle;
     6 import android.view.Menu;
     7 import android.view.MenuItem;
     8 import android.view.SubMenu;
     9 import android.widget.Toast;
    10 
    11 public class OptionMenu1Activitty extends Activity {
    12 
    13     @Override
    14     protected void onCreate(Bundle savedInstanceState) {
    15         // TODO Auto-generated method stub
    16         super.onCreate(savedInstanceState);
    17         setContentView(R.layout.activity_optionmenu1);
    18     }
    19 
    20     @Override
    21     public boolean onCreateOptionsMenu(Menu menu) {
    22         
    23         //直接Add菜单选项到Menu中
    24         menu.add(1000, 100, 0, "System menu"); 
    25         //获取添加的菜单选项,然后设置其图标
    26         MenuItem menuItem2=menu.add(1000, 101, 1, "User menu"); 
    27         menuItem2.setIcon(R.drawable.ic_launcher);
    28         //获取添加的菜单选项,增加一个Intent,点击后转向IntentActivity
    29         MenuItem menuItem3=menu.add(1000, 102, 2, "Intent menu"); 
    30         menuItem3.setIcon(R.drawable.ic_launcher);
    31         Intent intent=new Intent(OptionMenu1Activitty.this, IntentActivity.class);
    32         menuItem3.setIntent(intent);        
    33 
    34         //添加一个SubMenu,点击后弹出一个子菜单对话框
    35         SubMenu submenu=menu.addSubMenu(1000, 103, 3, "Sub menus");
    36         submenu.add(1000, 104, 4, "Sub ment1");
    37         submenu.add(1000, 105, 4, "Sub ment2");
    38         submenu.add(1000, 106, 4, "Sub ment3");
    39         return true;
    40     }
    41     
    42     @Override
    43     public boolean onOptionsItemSelected(MenuItem item) {
    44         boolean flag;
    45         switch (item.getItemId()) {
    46         case 100:
    47             Toast.makeText(OptionMenu1Activitty.this, "selected System menu", Toast.LENGTH_SHORT).show();
    48             flag=true;
    49             break;
    50         case 101:
    51             Toast.makeText(OptionMenu1Activitty.this, "selected User menu", Toast.LENGTH_SHORT).show();
    52             flag=true;
    53             break;
    54         case 104:
    55             Toast.makeText(OptionMenu1Activitty.this, "selected Sub menu1", Toast.LENGTH_SHORT).show();
    56             flag=true;
    57         default:
    58             flag=super.onOptionsItemSelected(item);
    59             break;
    60         }
    61         return flag;
    62     }
    63     
    64 }
    复制代码

      实现效果,Android2.3:

       使用XML资源文件定义选项菜单,XML资源文件:

    复制代码
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <menu xmlns:android="http://schemas.android.com/apk/res/android" >
     3 
     4     <item
     5         android:id="@+id/item1"
     6         android:showAsAction="never"
     7         android:title="System menu">
     8     </item>
     9     <item
    10         android:id="@+id/item2"
    11         android:showAsAction="never"
    12         android:title="User menu" 
    13         android:icon="@drawable/ic_launcher">
    14     </item>
    15     <item
    16         android:id="@+id/item3"
    17         android:showAsAction="never"
    18         android:title="Intent menu" 
    19         android:icon="@drawable/ic_launcher">
    20     </item>
    21     <group android:id="@+id/group_file" >
    22         <item android:id="@+id/menu_save" 
    23               android:title="menu group save" />
    24         <item android:id="@+id/menu_delete"
    25               android:title="menu group delete" />
    26     </group>
    27     <item android:id="@+id/file"
    28           android:title="Sub menus" >
    29         <!-- "file" submenu -->
    30         <menu>
    31             <item android:id="@+id/sub_menu1"
    32                   android:title="Sub menu1" />
    33             <item android:id="@+id/sub_menu21"
    34                   android:title="Sub menu2" />
    35             <item android:id="@+id/sub_menu3"
    36                   android:title="Sub menu3" />
    37         </menu>
    38     </item>
    39 </menu>
    复制代码

     Java代码:

    复制代码
     1 package com.example.menudemo;
     2 
     3 import android.app.Activity;
     4 import android.content.Intent;
     5 import android.os.Bundle;
     6 import android.view.Menu;
     7 import android.view.MenuItem;
     8 import android.widget.TextView;
     9 import android.widget.Toast;
    10 
    11 public class OptionMenu2Activitty extends Activity {
    12     private TextView  tv;
    13     @Override
    14     protected void onCreate(Bundle savedInstanceState) {
    15         // TODO Auto-generated method stub
    16         super.onCreate(savedInstanceState);
    17         setContentView(R.layout.activity_optionmenu1);
    18         tv=(TextView)findViewById(R.id.tvOptionMenu1);
    19         tv.setText("加载XML资源填充Menu");        
    20     }
    21     
    22     @Override
    23     public boolean onCreateOptionsMenu(Menu menu) {
    24         // 使用布局文件加载菜单
    25         getMenuInflater().inflate(R.menu.optionmenu2, menu);
    26         return super.onCreateOptionsMenu(menu);
    27     }
    28     
    29     @Override
    30     public boolean onOptionsItemSelected(MenuItem item) {
    31 
    32         switch (item.getItemId()) {
    33         case R.id.item1:
    34             Toast.makeText(OptionMenu2Activitty.this, "selected System menu", Toast.LENGTH_SHORT).show();
    35             return true;
    36         case R.id.item2:
    37             Toast.makeText(OptionMenu2Activitty.this, "selected User menu", Toast.LENGTH_SHORT).show();
    38             return true;
    39         case R.id.item3:
    40             Intent intent=new Intent(OptionMenu2Activitty.this, IntentActivity.class);
    41             startActivity(intent);
    42             return true;
    43         case R.id.menu_save:
    44             Toast.makeText(OptionMenu2Activitty.this, "file save", Toast.LENGTH_SHORT).show();
    45             return true;
    46         case R.id.sub_menu1:
    47             Toast.makeText(OptionMenu2Activitty.this, "Selected sub_menu1", Toast.LENGTH_SHORT).show();
    48             return true;
    49         default:
    50             return super.onOptionsItemSelected(item);
    51         }
    52         
    53         
    54     }
    55     
    56 }
    复制代码

      效果和使用Java代码声明菜单一样,这里就不再展示了。

    ContextMenu

      ContextMenu,上下文菜单提供了注册在View组件的菜单操作,它以一个浮动的窗口显示(类似于对话框),当用户长按某被注册了上下文菜单的视图,则触发上下文菜单显示。通常都用于ListView或者GridView等视图集合中。

      使用上下文菜单的步骤:

    1. 使用Activity.registerForContextMenu(View)方法为指定View注册上下文菜单。
    2. 在Activity或者Fragment中重写onCreateContextMenu()方法,当被注册的视图接受到长按事件后,系统调用onCreateContextMenu()方法,在这个方法中声明上下文菜单。
    3. 实现onContextItemSelected()方法,用于响应菜单想的选中。

      示例,菜单XML资源文件代码:

    复制代码
     1 <menu xmlns:android="http://schemas.android.com/apk/res/android" >
     2 
     3      <item
     4         android:id="@+id/context_copy"
     5         android:orderInCategory="100"
     6         android:showAsAction="never"
     7         android:title="Copy"/>
     8     <item
     9         android:id="@+id/context_edit"
    10         android:orderInCategory="100"
    11         android:showAsAction="never"
    12         android:title="Edit"/>
    13     <item
    14         android:id="@+id/context_delete"
    15         android:orderInCategory="100"
    16         android:showAsAction="never"
    17         android:title="Delete"/>
    18 </menu>
    复制代码

      Java代码:

    复制代码
     1 package com.example.menudemo;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 import android.app.Activity;
     7 import android.os.Bundle;
     8 import android.view.ContextMenu;
     9 import android.view.MenuInflater;
    10 import android.view.MenuItem;
    11 import android.view.View;
    12 import android.view.ContextMenu.ContextMenuInfo;
    13 import android.widget.AdapterView.AdapterContextMenuInfo;
    14 import android.widget.ArrayAdapter;
    15 import android.widget.ListView;
    16 import android.widget.Toast;
    17 
    18 public class ContextMenu1 extends Activity {
    19     private ListView listview;
    20     private List<String> dataList;
    21     @Override
    22     protected void onCreate(Bundle savedInstanceState) {
    23         super.onCreate(savedInstanceState);
    24         setContentView(R.layout.activity_contextmenu1);
    25         listview=(ListView)findViewById(R.id.listView1);
    26         dataList=getData();
    27         ArrayAdapter<String> adapter=new  ArrayAdapter<String>(ContextMenu1.this,android.R.layout.simple_list_item_1, dataList);
    28         listview.setAdapter(adapter);
    29         //为ListView注册上下文菜单
    30         registerForContextMenu(listview);
    31     }
    32     
    33     @Override
    34     public void onCreateContextMenu(ContextMenu menu, View v,
    35             ContextMenuInfo menuInfo) {
    36         super.onCreateContextMenu(menu, v, menuInfo);
    37         //填充一个XML菜单文件
    38         MenuInflater inflater = getMenuInflater();
    39         inflater.inflate(R.menu.contextmenu, menu);
    40     }
    41     
    42     @Override
    43     public boolean onContextItemSelected(MenuItem item) {
    44         //获取上下文菜单绑定的AdapterView的额外信息
    45         AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
    46         switch (item.getItemId()) {
    47         case R.id.context_copy:
    48             Toast.makeText(ContextMenu1.this, "copy "+dataList.get(info.position), Toast.LENGTH_SHORT).show();
    49             return true;
    50         case R.id.context_delete:
    51             Toast.makeText(ContextMenu1.this, "delete "+dataList.get(info.position), Toast.LENGTH_SHORT).show();
    52             return true;
    53         case R.id.context_edit:
    54             Toast.makeText(ContextMenu1.this, "edit " +dataList.get(info.position), Toast.LENGTH_SHORT).show();
    55             return true;
    56         default:
    57             return super.onContextItemSelected(item);
    58         }        
    59     }
    60     //ListView数据
    61     public List<String> getData()
    62     {        
    63         List<String> data=new ArrayList<String>();
    64         for(int i=0;i<8;i++)
    65         {
    66             data.add("item"+i);
    67         }
    68         return data;
    69     }    
    70 }
    复制代码

      效果展示,Android4.0:

    ActionMode

      ActionMode,是一个系统实现的用户交互,当用户使用ActionMode后,选择一个选项,一个上下文操作栏会出现在屏幕的顶端,呈现出用户可以对当前选中项目进行的操作选项。进入这种状态可以通过后退按钮或者调用finish()退出。ActionMode为Android3.0之后的支持,所以在开发3.0之后的应用,推荐使用ActionMode,而不是ContextMenu。

      使用ActionMode的步骤:

    1. 实现ActionMode.Callback接口。在它的回调方法中,可以设置操作的上下文操作栏。
    2. 在需要显示上下文操作栏的时候,调用startActionMode(ActionMode.Callback)。

      ActionMode.Callback是ActionMode定义的一个内部接口,这个接口需要实现下面四个方法:

    • boolean onCreateActionMode(ActionMode mode,Menu menu):第一次被创建的时候调用。
    • boolean onPrepareActionMode(ActionMode mode,Menu menu):刷新菜单列表的时候被调用,一般使用false即可。
    • boolean onActionItemClicked(ActionMode mode,MenuItem item):菜单项被选中的时候被调用。
    • void onDestroyActionMode(ActionMode mode):退出或销毁的时候被调用。

      示例:

    复制代码
      1 package com.example.menudemo;
      2 
      3 import java.util.ArrayList;
      4 import java.util.List;
      5 
      6 import android.annotation.SuppressLint;
      7 import android.app.Activity;
      8 import android.os.Bundle;
      9 import android.view.ActionMode;
     10 import android.view.ActionMode.Callback;
     11 import android.view.Menu;
     12 import android.view.MenuInflater;
     13 import android.view.MenuItem;
     14 import android.view.View;
     15 import android.widget.AdapterView;
     16 import android.widget.AdapterView.AdapterContextMenuInfo;
     17 import android.widget.AdapterView.OnItemLongClickListener;
     18 import android.widget.ArrayAdapter;
     19 import android.widget.ListView;
     20 import android.widget.Toast;
     21 
     22 public class ActionModeMenu1 extends Activity {
     23     private ListView listview;
     24     private List<String> dataList;
     25     private ActionMode mActionMode;
     26     @Override
     27     protected void onCreate(Bundle savedInstanceState) {
     28         // TODO Auto-generated method stub
     29         super.onCreate(savedInstanceState);
     30         setContentView(R.layout.activity_contextmenu1);
     31         listview=(ListView)findViewById(R.id.listView1);
     32         dataList=getData();
     33         ArrayAdapter<String> adapter=new  ArrayAdapter<String>(ActionModeMenu1.this,android.R.layout.simple_list_item_1, dataList);
     34         listview.setAdapter(adapter);
     35         listview.setOnItemLongClickListener(new OnItemLongClickListener() {
     36             @SuppressLint("NewApi")
     37             @Override
     38             public boolean onItemLongClick(AdapterView<?> parent, View view,
     39                     int position, long id) {        
     40                 if (mActionMode != null) {
     41                     return false;
     42                 }
     43                 //显示ActionMode
     44                 mActionMode = startActionMode(mActionModeCallback);
     45                 //标记选中项的下表
     46                 mActionMode.setTag(position);
     47                 //标记ListView为可选状态
     48                 view.setSelected(true);
     49                 return true;
     50             }
     51         });
     52     }
     53     public List<String> getData()
     54     {
     55         List<String> data=new ArrayList<String>();
     56         for(int i=0;i<8;i++)
     57         {
     58             data.add("item"+i);
     59         }
     60         return data;
     61     }
     62     
     63     private ActionMode.Callback mActionModeCallback=new Callback() {
     64         
     65         @Override
     66         public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
     67             //刷新菜单列表的时候被调用,但是一般无需刷新
     68             return false;
     69         }
     70         
     71         @Override
     72         public void onDestroyActionMode(ActionMode mode) {
     73             //销毁ActionMode
     74             mActionMode = null;
     75         }
     76         
     77         @Override
     78         public boolean onCreateActionMode(ActionMode mode, Menu menu) {
     79             //创建ActionMode
     80             //使用资源文件填充
     81             MenuInflater inflater = mode.getMenuInflater();
     82             inflater.inflate(R.menu.contextmenu, menu);
     83             return true;
     84         }
     85 
     86         @Override
     87         public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
     88             //获取选项中下表
     89             int position=(Integer)mode.getTag();
     90             switch (item.getItemId()) {
     91             case R.id.context_copy:
     92                 Toast.makeText(ActionModeMenu1.this, "copy "+dataList.get(position), Toast.LENGTH_SHORT).show();
     93                 //finish退出ActionMode模式
     94                 mode.finish();
     95                 return true;
     96             case R.id.context_delete:
     97                 Toast.makeText(ActionModeMenu1.this, "delete "+dataList.get(position), Toast.LENGTH_SHORT).show();
     98                 mode.finish();
     99                 return true;
    100             case R.id.context_edit:
    101                 Toast.makeText(ActionModeMenu1.this, "edit " +dataList.get(position), Toast.LENGTH_SHORT).show();
    102                 mode.finish();
    103                 return true;
    104             default:
    105                 return false;
    106         }
    107         }
    108     };
    109     
    110     
    111 }
    复制代码

     效果展示,Android4.0:

     

    PopupMenu

      PopupMenu,弹出菜单,一个模态形式展示的弹出风格的菜单,绑在在某个View上,一般出现在被绑定的View的下方(如果下方有空间)。

      使用PopupMenu的步骤:

    1. 通过PopupMenu的构造函数实例化一个PopupMenu对象,需要传递一个当前上下文对象以及绑定的View。
    2. 调用PopupMenu.setOnMenuItemClickListener()设置一个PopupMenu选项的选中事件。
    3. 使用MenuInflater.inflate()方法加载一个XML文件到PopupMenu.getMenu()中。
    4. 在需要的时候调用PopupMenu.show()方法显示。

      示例:

    复制代码
     1     public void showPopup(View v){
     2         PopupMenu popup=new PopupMenu(MainActivity.this, v);
     3         popup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
     4             
     5             @Override
     6             public boolean onMenuItemClick(MenuItem item) {
     7                 switch (item.getItemId()) {
     8                 case R.id.context_copy:
     9                     Toast.makeText(MainActivity.this, "select copy ", Toast.LENGTH_SHORT).show();
    10                     return true;
    11                 case R.id.context_delete:
    12                     Toast.makeText(MainActivity.this, " select delete ", Toast.LENGTH_SHORT).show();
    13                     return true;
    14                 case R.id.context_edit:
    15                     Toast.makeText(MainActivity.this, " select edit ", Toast.LENGTH_SHORT).show();
    16                     return true;
    17                     default :
    18                     return false;
    19                 }
    20             }
    21         });
    22         popup.getMenuInflater().inflate(R.menu.contextmenu,popup.getMenu());
    23         popup.show();
    24     }
    复制代码

      效果展示,Android4.0:

      源码下载

    总结

      以上就讲解了Android下Menu的使用。因为上面的所有示例均在一个项目中完成的,所以有些低版本的操作,需要更改AndroidManifest.xml文件中的最低支持版本,改到8即可。在现在的实际开发中,最好还是使用对高版本只是的ActionBar、ActionMode、PopupMenu比较好。

  • 相关阅读:
    如何提高Android代码的安全性
    Android数据库安全解决方案,使用SQLCipher进行加解密
    【Android UI设计与开发】第16期:滑动菜单栏(一)
    4种必须知道的Android屏幕自适应解决方案
    android权限大全
    在Windows7下构建Android的开发环境
    Android 悬浮歌词(迷你歌词)效果解读 (转)
    大数据量数据库优化(转)
    使用isInEditMode解决可视化编辑器无法识别自定义控件的问题(转)
    导入开源项目后报:Caused by: java.lang.ClassNotFoundException: Didn't find class
  • 原文地址:https://www.cnblogs.com/shitaotao/p/7635763.html
Copyright © 2011-2022 走看看