zoukankan      html  css  js  c++  java
  • Android系列之UI组件----Menu菜单

    【声明】

    欢迎转载,但请保留文章原始出处→_→

    生命壹号:http://www.cnblogs.com/smyhvae/

    文章来源:http://www.cnblogs.com/smyhvae/p/4133292.html

     

    【正文】

    从官方文档了解到,从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之后才有支持。
    • Popup 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资源变成一个可编程的对象。

    一、Options menu选项菜单:

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

    创建选项菜单的核心步骤:

    (1)重写Activity的onCreateOptionMenu(Menu menu)方法,当菜单第一次被加载时调用

    (2)调用Menu 的add( )方法添加菜单项(MenuItem),同时可以调用MenuItem的setIcon()方法为菜单项设置图标(注:Android 3.0之后,即使添加了图标也不会显示)

    (3)重写Activity的OptionsItemSelected(MenuItem item)来响应菜单项(MenuItem)的点击事件

    来看一下具体的代码实现:

    新建Android工程MenuTest:

    【方式一】通过配置文件添加Menu选项

    (1)在res/menu/main.xml中定义菜单项。main.xml的代码如下:

    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        tools:context="com.example.menutest.MainActivity" >
    
        <item
            android:id="@+id/start"
            android:orderInCategory="100"
            android:showAsAction="never"
            android:title="@string/start"/>
        
            <item
            android:id="@+id/over"
            android:orderInCategory="200"
            android:showAsAction="never"
            android:title="@string/over"/>
    
    </menu>

    注:第9行和第15行的字符串引用,需要提前在strings.xml文件中设置好。

    (2)MainActivity.java:

     1 package com.example.menutest;
     2 
     3 import android.app.Activity;
     4 import android.os.Bundle;
     5 import android.view.Menu;
     6 import android.view.MenuItem;
     7 import android.widget.Toast;
     8 
     9 
    10 public class MainActivity extends Activity {
    11 
    12     @Override
    13     protected void onCreate(Bundle savedInstanceState) {
    14         super.onCreate(savedInstanceState);
    15         setContentView(R.layout.activity_main);
    16     }
    17 
    18 
    19     //重写onCreateOptionMenu(Menu menu)方法,当菜单第一次被加载时调用
    20     @Override
    21     public boolean onCreateOptionsMenu(Menu menu) {
    22         // Inflate the menu; this adds items to the action bar if it is present.
    23         //填充选项菜单(读取XML文件、解析、加载到Menu组件上)
    24         getMenuInflater().inflate(R.menu.main, menu);
    25         return true;
    26     }
    27 
    28     //重写OptionsItemSelected(MenuItem item)来响应菜单项(MenuItem)的点击事件(根据id来区分是哪个item)
    29     @Override
    30     public boolean onOptionsItemSelected(MenuItem item) {
    31         // Handle action bar item clicks here. The action bar will
    32         // automatically handle clicks on the Home/Up button, so long
    33         // as you specify a parent activity in AndroidManifest.xml.
    34         switch (item.getItemId()) {
    35         case R.id.start:
    36             Toast.makeText(this, "开始游戏", Toast.LENGTH_SHORT).show();
    37             break;
    38         case R.id.over:
    39             Toast.makeText(this, "结束游戏", Toast.LENGTH_SHORT).show();
    40             break;
    41 
    42         default:
    43             break;
    44         }
    45         return super.onOptionsItemSelected(item);
    46     }
    47 }

    核心代码是第24行:引用布局文件menu.xml,然后在30行的方法中添加MenuItem的点击事件。

    运行程序,效果如下:

    如果想让MenuItem变成ActionBar的形式,可以修改res/menu/main.xml中的android:showAsAction属性,它的属性值一共有下面几种:

    其中,ifRoom表示:如果有空间,就显示出来。withText表示:只显示文本(如果配了图标的话)。如果将属性设置为always,效果如下:

    如果需要添加子菜单,可以修改menu.xml文件为如下所示:

    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        tools:context="com.example.menutest.MainActivity" >
    
        <item
            android:id="@+id/start"
            android:orderInCategory="100"
            android:showAsAction="never"
            android:title="@string/start"/>
        <item
            android:id="@+id/over"
            android:orderInCategory="200"
            android:showAsAction="never"
            android:title="@string/over"/>
        
        <!-- 子菜单 -->
        <item
            android:id="@+id/setting"
            android:title="setting">
            <menu>
                <item
                    android:id="@+id/setting1"
                    android:orderInCategory="300"
                    android:showAsAction="never"
                    android:title="声音設置"/>
                <item
                    android:id="@+id/setting2"
                    android:orderInCategory="400"
                    android:showAsAction="never"
                    android:title="背景設置"/>
            </menu>
        </item>
    
    </menu>

    于是,子菜单的点击事件为:

        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            switch (item.getItemId()) {
            case R.id.start:
                Toast.makeText(this, "开始游戏", Toast.LENGTH_SHORT).show();
                break;
            case R.id.over:
                Toast.makeText(this, "结束游戏", Toast.LENGTH_SHORT).show();
                break;
                
            case R.id.setting1:
                Toast.makeText(this, "声音設置", Toast.LENGTH_SHORT).show();
                break;
                
            case R.id.setting2:
                Toast.makeText(this, "背景設置", Toast.LENGTH_SHORT).show();
                break;
            default:
                break;
            }
            return super.onOptionsItemSelected(item);
        }

    运行效果如下:

    【方式二】通过Java代码添加Menu选项:

    当然了,上方的方式一是通过xml文件来添加Menu选项的,下面我们通过Java代码来添加Menu选项(此时已经不需要menu.xml文件了)。修改MainActivity.java,代码如下: 

    MainActivity.java:

     1 package com.example.menutest;
     2 
     3 import android.app.Activity;
     4 import android.os.Bundle;
     5 import android.view.Menu;
     6 import android.view.MenuItem;
     7 import android.view.SubMenu;
     8 import android.widget.Toast;
     9 
    10 
    11 public class MainActivity extends Activity {
    12 
    13     
    14     private static final int START_ITEM = Menu.FIRST;  //Menu.FIRST的值就是1
    15     private static final int OVER_ITEM = Menu.FIRST+1;
    16     private static final int SET_ITEM1 = Menu.FIRST+2;
    17     private static final int SET_ITEM2 = Menu.FIRST+3;
    18     
    19     
    20     @Override
    21     protected void onCreate(Bundle savedInstanceState) {
    22         super.onCreate(savedInstanceState);
    23         setContentView(R.layout.activity_main);
    24     }
    25 
    26 
    27     //重写onCreateOptionMenu(Menu menu)方法,当菜单第一次被加载时调用
    28     @Override
    29     public boolean onCreateOptionsMenu(Menu menu) {
    30         // Inflate the menu; this adds items to the action bar if it is present.
    31         //填充选项菜单(读取XML文件、解析、加载到Menu组件上)
    32        // getMenuInflater().inflate(R.menu.main, menu);
    33         
    34         //通过代码的方式来添加Menu
    35         //添加菜单项(组ID,菜单项ID,排序,标题)
    36         menu.add(0, START_ITEM, 100, "Start");
    37         menu.add(0, OVER_ITEM, 200, "Over");
    38         //添加子菜单
    39         SubMenu sub1 = menu.addSubMenu("setting");
    40         sub1.add(1, SET_ITEM1, 300, "声音设置");
    41         sub1.add(1, SET_ITEM2, 400, "背景设置");
    42         
    43         return true;
    44     }
    45 
    46     //重写OptionsItemSelected(MenuItem item)来响应菜单项(MenuItem)的点击事件(根据id来区分是哪个item)
    47     @Override
    48     public boolean onOptionsItemSelected(MenuItem item) {
    49         // Handle action bar item clicks here. The action bar will
    50         // automatically handle clicks on the Home/Up button, so long
    51         // as you specify a parent activity in AndroidManifest.xml.
    52         switch (item.getItemId()) {
    53         case START_ITEM:
    54             Toast.makeText(this, "开始游戏", Toast.LENGTH_SHORT).show();
    55             break;
    56         case OVER_ITEM:
    57             Toast.makeText(this, "结束游戏", Toast.LENGTH_SHORT).show();
    58             break;
    59             
    60         case SET_ITEM1:
    61             Toast.makeText(this, "声音設置", Toast.LENGTH_SHORT).show();
    62             break;
    63             
    64         case SET_ITEM2:
    65             Toast.makeText(this, "背景設置", Toast.LENGTH_SHORT).show();
    66             break;
    67 
    68         default:
    69             break;
    70         }
    71         return super.onOptionsItemSelected(item);
    72     }
    73 }

    注意第35行对各个参数的解释。

    运行程序,效果和上方gif图的效果是一样的。

    总结:推荐用方式1来做。

    二、Context menu:上下文菜单

    顾名思义 与上下文(环境)有关。操作时需要长时间按住某个item不放,就会弹出Context menu。效果如下:

    创建上下文菜单的核心步骤:

    (1)覆盖Activity的onCreateContextMenu(Menu menu)方法,调用Menu的add()方法添加菜单项(MenuItem)

    (2)覆盖Activity的onContextItemSelected(MenuItem iitem)来响应事件

    (3)调用registerForContextMenu()方法来为视图注册上下文菜单。

    现在通过代码来实现。

    重新建一个Android工程MenuTest02,步骤如下:

    我们现在activity_main.xml中添加一个按钮button1,代码就不写了。然后继续:

    (1)在res/menu/main.xml中定义菜单项。main.xml的代码如下:

    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        tools:context="com.example.menutest02.MainActivity" >
    
        <item
            android:id="@+id/start"
            android:orderInCategory="100"
            android:showAsAction="never"
            android:title="@string/start"/>
        <item
            android:id="@+id/over"
            android:orderInCategory="200"
            android:showAsAction="never"
            android:title="@string/over"/>
    
    </menu>

    (2)MainActivity.java:

     1 package com.example.menutest02;
     2 
     3 import android.app.Activity;
     4 import android.os.Bundle;
     5 import android.view.ContextMenu;
     6 import android.view.MenuItem;
     7 import android.view.View;
     8 import android.view.ContextMenu.ContextMenuInfo;
     9 import android.widget.Button;
    10 import android.widget.Toast;
    11 
    12 
    13 public class MainActivity extends Activity   {
    14 
    15     private Button button1;
    16     @Override
    17     protected void onCreate(Bundle savedInstanceState) {
    18         super.onCreate(savedInstanceState);
    19         setContentView(R.layout.activity_main);
    20         button1 = (Button)findViewById(R.id.button1);
    21         //为按钮绑定上下文菜单(注意不是绑定监听器)
    22         registerForContextMenu(button1);
    23     }
    24     
    25     //创建上下文菜单
    26     @Override
    27     public void onCreateContextMenu(ContextMenu menu, View v,
    28             ContextMenuInfo menuInfo) {
    29         super.onCreateContextMenu(menu, v, menuInfo);
    30         
    31         getMenuInflater().inflate(R.menu.main, menu);
    32     }
    33     
    34     //上下文菜单的触发事件
    35     @Override
    36     public boolean onContextItemSelected(MenuItem item) {
    37         switch (item.getItemId()) {
    38         case R.id.start:
    39             Toast.makeText(this, "开始···", Toast.LENGTH_SHORT).show();
    40             break;
    41             
    42         case R.id.over:
    43             Toast.makeText(this, "结束···", Toast.LENGTH_SHORT).show();
    44             break;
    45 
    46         default:
    47             break;
    48         }        
    49         
    50         return super.onContextItemSelected(item);
    51     }
    52 
    53 }

    核心代码是第22行:为按钮button1绑定上下文菜单。注意不是绑定监听器哦,不要一看到按钮就绑定监听器哈。

    注:一个界面中只能有一个上下文菜单

    运行程序,长按button,效果如下:

    注:如果是在java代码中添加Menu,用参数menu来天添加就行了。

    三、Popup menu:弹出式菜单

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

    注意:弹出菜单是在API 11和更高版本上才有效的。

    核心步骤:

    (1)通过PopupMenu的构造函数实例化一个PopupMenu对象,需要传递一个当前上下文对象以及绑定的View。

    (2)调用PopupMenu.setOnMenuItemClickListener()设置一个PopupMenu选项的选中事件。

    (3)使用MenuInflater.inflate()方法加载一个XML文件到PopupMenu.getMenu()中。

    (4)在需要的时候调用PopupMenu.show()方法显示。

    现在通过代码来实现。重新新建一个工程文件MenuTest03。步骤如下:

    先在布局文件activity_main.xml中加一个按钮,代码略。

    (1)在res/menu/main.xml中定义菜单项。main.xml的代码如下:

    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        tools:context="com.example.menutest03.MainActivity" >
    
        <item
            android:id="@+id/copy"
            android:orderInCategory="100"
            android:title="复制"/>
        
        <item
            android:id="@+id/delete"
            android:orderInCategory="100"
            android:title="粘贴"/>
    
    </menu>

    (2)MainActivity.java:

     1 package com.example.menutest03;
     2 
     3 import android.app.Activity;import android.os.Bundle;
     4 import android.view.MenuInflater;
     5 import android.view.MenuItem;
     6 import android.view.View;
     7 import android.view.View.OnClickListener;
     8 import android.widget.Button;
     9 import android.widget.PopupMenu;
    10 import android.widget.PopupMenu.OnMenuItemClickListener;
    11 import android.widget.Toast;
    12 
    13 
    14 public class MainActivity extends Activity implements OnClickListener,OnMenuItemClickListener{
    15 
    16     
    17     private Button button1;
    18     @Override
    19     protected void onCreate(Bundle savedInstanceState) {
    20         super.onCreate(savedInstanceState);
    21         setContentView(R.layout.activity_main);
    22         button1 = (Button)findViewById(R.id.button1);
    23         button1.setOnClickListener(this);
    24     }
    25 
    26     //点击按钮后,加载弹出式菜单
    27     @Override
    28     public void onClick(View v) {
    29         //创建弹出式菜单对象(最低版本11)
    30         PopupMenu popup = new PopupMenu(this, v);//第二个参数是绑定的那个view
    31         //获取菜单填充器
    32         MenuInflater inflater = popup.getMenuInflater();
    33         //填充菜单
    34         inflater.inflate(R.menu.main, popup.getMenu());
    35         //绑定菜单项的点击事件
    36         popup.setOnMenuItemClickListener(this);
    37         popup.show(); //这一行代码不要忘记了
    38         
    39     }
    40 
    41     //弹出式菜单的单击事件处理
    42     @Override
    43     public boolean onMenuItemClick(MenuItem item) {
    44         // TODO Auto-generated method stub
    45         switch (item.getItemId()) {
    46         case R.id.copy:
    47             Toast.makeText(this, "复制···", Toast.LENGTH_SHORT).show();
    48             break;
    49 
    50         case R.id.delete:
    51             Toast.makeText(this, "删除···", Toast.LENGTH_SHORT).show();
    52             break;
    53         default:
    54             break;
    55         }
    56         return false;
    57     }
    58     
    59 }

    注意14行代码绑定了两个监听器:OnClickListener和OnMenuItemClickListener。 在绑定OnMenuItemClickListener监听器时,选的是下面这个:

    如果是在API 14及以上版本,32行34行可以合并为:popup.inflate(R.menu.main, popup.getMenu());

    注意第37行代码不要忘记show。

    运行程序,单击button,效果如下:

    最后,附上整个文章的代码:

    【工程文件】

    链接:http://pan.baidu.com/s/1eQ6EnUq 

    密码:438o

  • 相关阅读:
    修改 Mac 默认 PHP 运行环境,给 MAMP 配置全局 Composer
    修改 Mac 默认 PHP 运行环境,给 MAMP 配置全局 Composer
    Intellij Idea/Webstorm/Phpstorm 的高效快捷键
    Intellij Idea/Webstorm/Phpstorm 的高效快捷键
    管理工具推荐
    mongo find
    redis 工具
    Redis Quick Start [熟练版]
    Redis cluster
    redis cluster 使用中出现的问题
  • 原文地址:https://www.cnblogs.com/qianguyihao/p/4133292.html
Copyright © 2011-2022 走看看