Android系列之UI组件----Menu菜单

简介:

【正文】

从官方文档了解到,从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,效果如下:

相关文章
|
1月前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
2月前
|
存储 Android开发 开发者
深入理解安卓应用开发的核心组件
【10月更文挑战第8天】探索Android应用开发的精髓,本文带你了解安卓核心组件的奥秘,包括Activity、Service、BroadcastReceiver和ContentProvider。我们将通过代码示例,揭示这些组件如何协同工作,构建出功能强大且响应迅速的应用程序。无论你是初学者还是资深开发者,这篇文章都将为你提供新的视角和深度知识。
|
2月前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
101 0
|
23天前
|
XML 搜索推荐 前端开发
安卓开发中的自定义视图:打造个性化UI组件
在安卓应用开发中,自定义视图是一种强大的工具,它允许开发者创造独一无二的用户界面元素,从而提升应用的外观和用户体验。本文将通过一个简单的自定义视图示例,引导你了解如何在安卓项目中实现自定义组件,并探讨其背后的技术原理。我们将从基础的View类讲起,逐步深入到绘图、事件处理以及性能优化等方面。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧。
|
1月前
|
XML 前端开发 Android开发
Android:UI:Drawable:View/ImageView与Drawable
通过本文的介绍,我们详细探讨了Android中Drawable、View和ImageView的使用方法及其相互关系。Drawable作为图像和图形的抽象表示,提供了丰富的子类和自定义能力,使得开发者能够灵活地实现各种UI效果。View和ImageView则通过使用Drawable实现了各种图像和图形的显示需求。希望本文能为您在Android开发中使用Drawable提供有价值的参考和指导。
40 2
|
2月前
|
XML 前端开发 Java
安卓应用开发中的自定义View组件
【10月更文挑战第5天】自定义View是安卓应用开发的一块基石,它为开发者提供了无限的可能。通过掌握其原理和实现方法,可以创造出既美观又实用的用户界面。本文将引导你了解自定义View的创建过程,包括绘制技巧、事件处理以及性能优化等关键步骤。
|
2月前
|
测试技术 数据库 Android开发
深入解析Android架构组件——Jetpack的使用与实践
本文旨在探讨谷歌推出的Android架构组件——Jetpack,在现代Android开发中的应用。Jetpack作为一系列库和工具的集合,旨在帮助开发者更轻松地编写出健壮、可维护且性能优异的应用。通过详细解析各个组件如Lifecycle、ViewModel、LiveData等,我们将了解其原理和使用场景,并结合实例展示如何在实际项目中应用这些组件,提升开发效率和应用质量。
54 6
|
3月前
|
存储 开发框架 数据可视化
深入解析Android应用开发中的四大核心组件
本文将探讨Android开发中的四大核心组件——Activity、Service、BroadcastReceiver和ContentProvider。我们将深入了解每个组件的定义、作用、使用方法及它们之间的交互方式,以帮助开发者更好地理解和应用这些组件,提升Android应用开发的能力和效率。
290 5
|
3月前
|
XML Android开发 UED
💥Android UI设计新风尚!掌握Material Design精髓,让你的界面颜值爆表!🎨
随着移动应用市场的蓬勃发展,用户对界面设计的要求日益提高。为此,掌握由Google推出的Material Design设计语言成为提升应用颜值和用户体验的关键。本文将带你深入了解Material Design的核心原则,如真实感、统一性和创新性,并通过丰富的组件库及示例代码,助你轻松打造美观且一致的应用界面。无论是色彩搭配还是动画效果,Material Design都能为你的Android应用增添无限魅力。
87 1
|
3月前
|
缓存 搜索推荐 Android开发
安卓应用开发中的自定义View组件实践
【9月更文挑战第10天】在安卓开发领域,自定义View是提升用户体验和实现界面个性化的重要手段。本文将通过一个实际案例,展示如何在安卓项目中创建和使用自定义View组件,包括设计思路、实现步骤以及可能遇到的问题和解决方案。文章不仅提供了代码示例,还深入探讨了自定义View的性能优化技巧,旨在帮助开发者更好地掌握这一技能。