Android为我们提供了3中菜单:
- 选项菜单(Option Menu)
- 上下文菜单(Context Menu)
- 弹出菜单(Popup Menu)
选项菜单(Option Menu)
选项菜单就是当我们单击硬件设备上的菜单按钮而弹出的菜单(在android11(Android3.0)及以后版本通过ActionBars来实现,下面我们会讲到)
要构建选择菜单我们一般需要 重载 Activity的onCreateOptionsMenu(Menu menu)方法来创建选项菜单
- 通过硬编码来实现
- 通过资源文件来构建
下面我们分别通过实例来演示选项菜单的构建(注:以下实例都在Android4.1.2运行通过)
首先我们构建一个Android项目:
1.File -–>New—>Project—>Android Application Project来构建一个Android Project
这里我命名为:AD_MenusDemo,入口Activity命名为MainActivity
我们的项目结构如下图所示:
通过硬编码来实现
1.我们修改入口Activity对应的布局文件activity_main.xml,添加4个Button:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/LinearLayout1" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/byresourceButton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/btn_menusby_resources" /> <Button android:id="@+id/bycodingButton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/btn_menusby_coding" /> <Button android:id="@+id/contextMenuButton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/btn_contextmenu" /> <Button android:id="@+id/popupMenuButton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/btn_popuptmenu" /> </LinearLayout>2.我们添加3个Activity:MenuByCodingActivity、MenuByResourceActivity、ContextMenuActivity
3.我们打开入口类:MainActivity,初始化Button如下:
package com.jeriffe.android.app; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.MenuInflater; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.PopupMenu; public class MainActivity extends Activity { public Button btnCreateByResource, btnCreateByCoding, btnPopupMenu, btnContextMenu; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); SetupViews(); } private void SetupViews() { btnCreateByResource = (Button) findViewById(R.id.byresourceButton); btnCreateByResource.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(MainActivity.this, MenuByResourceActivity.class); startActivity(intent); } }); btnCreateByCoding = (Button) findViewById(R.id.bycodingButton); btnCreateByCoding.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(MainActivity.this, MenuByCodingActivity.class); startActivity(intent); } }); btnContextMenu = (Button) findViewById(R.id.contextMenuButton); btnContextMenu.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(MainActivity.this, ContextMenuActivity.class); startActivity(intent); } }); btnPopupMenu = (Button) findViewById(R.id.popupMenuButton); btnPopupMenu.setOnClickListener(new OnClickListener() { @SuppressLint("NewApi") public void onClick(View v) { PopupMenu popup = new PopupMenu(MainActivity.this, v); MenuInflater inflater = popup.getMenuInflater(); inflater.inflate(R.menu.activity_menu_by_resource, popup.getMenu()); popup.show(); } }); } }4.我们编辑MenuByCodingActivity如下:
package com.jeriffe.android.app; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.SubMenu; public class MenuByCodingActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_menu_by_coding); setTitle("硬编码构建菜单"); } @Override public boolean onCreateOptionsMenu(Menu menu) { /* * add()方法的四个参数,依次是: 1、组别,如果不分组的话就写Menu.NONE, * 2、Id,这个很重要,Android根据这个Id来确定不同的菜单 3、顺序,那个菜单现在在前面由这个参数的大小决定 * 4、文本,菜单的显示文本 */ SubMenu file = menu.addSubMenu(0, Menu.FIRST, 0, "File"); SubMenu edit = menu.addSubMenu(0, Menu.FIRST + 10, 0, "Edit"); SubMenu help = menu.addSubMenu(0, Menu.FIRST + 20, 0, "Help"); file.add(1, Menu.FIRST + 11, 0, "New"); file.add(1, Menu.FIRST + 12, 1, "Open"); file.add(1, Menu.FIRST + 13, 2, "Save"); file.add(1, Menu.FIRST + 14, 3, "Exit"); edit.add(2, Menu.FIRST + 11, 0, "Cut"); edit.add(2, Menu.FIRST + 12, 1, "Copy"); edit.add(2, Menu.FIRST + 13, 2, "Paste"); help.add(3, Menu.FIRST + 21, 0, "About"); help.add(3, Menu.FIRST + 22, 1, "Check Update"); return true; } }5.运行程序,主界面如下图左一:
6.我们点击第二个Button(通过硬编码构建选项菜单)会看到如上图左边第二个,我们点击红色圈圈中的Action overflow会看到左3
点击File会看到左4,点击Edit会看到左5。
7.如果我们要实现单击某一个菜单项来触发事件如何操作?
这里也是so easy,我们只需重载onOptionsItemSelected(MenuItem item)方法即可。我们还可以实现菜单项,或者菜单组的单选设置,这里我们可以通过以下2格方法:
setCheckable(boolean checkable)
onOptionsItemSelected(MenuItem item)
代码如下:
public class MenuByCodingActivity extends Activity { @Override public boolean onCreateOptionsMenu(Menu menu) { /* * add()方法的四个参数,依次是: 1、组别,如果不分组的话就写Menu.NONE, * 2、Id,这个很重要,Android根据这个Id来确定不同的菜单 3、顺序,那个菜单现在在前面由这个参数的大小决定 * 4、文本,菜单的显示文本 */ SubMenu file = menu.addSubMenu(0, Menu.FIRST, 0, "File"); SubMenu edit = menu.addSubMenu(0, Menu.FIRST + 10, 0, "Edit"); SubMenu help = menu.addSubMenu(0, Menu.FIRST + 20, 0, "Help"); file.add(1, Menu.FIRST + 11, 0, "New"); file.add(1, Menu.FIRST + 12, 1, "Open"); file.add(1, Menu.FIRST + 13, 2, "Save"); file.add(1, Menu.FIRST + 14, 3, "Exit"); MenuItem item = edit.add(2, Menu.FIRST + 11, 0, "Cut"); /* * setCheckable (boolean checkable) :设置菜单项是否可以被勾选 */ item.setCheckable(true); edit.add(2, Menu.FIRST + 12, 1, "Copy"); edit.add(2, Menu.FIRST + 13, 2, "Paste"); /* * setGroupCheckable(int group, boolean checkable, boolean exclusive) * 设置group下的所有菜单项是否可以被勾选 如果第三个参数exclusive=true,则这格group下的菜单项将作为一组单选菜单项 */ edit.setGroupCheckable(2, true, false); help.add(3, Menu.FIRST + 21, 0, "About"); help.add(3, Menu.FIRST + 22, 1, "Check Update"); help.setGroupCheckable(3, true, true); return true; } @Override /* * 我们可以 重载onOptionsItemSelected方法来实现MenuItem单击事件处理,也可以通过实现监听器来操作 */ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case Menu.FIRST: Toast.makeText(MenuByCodingActivity.this, "File 菜单被选择", Toast.LENGTH_LONG).show(); break; case Menu.FIRST + 10: Toast.makeText(MenuByCodingActivity.this, "Edit 菜单被选择", Toast.LENGTH_LONG).show(); break; case Menu.FIRST + 20: Toast.makeText(MenuByCodingActivity.this, "Help 菜单被选择", Toast.LENGTH_LONG).show(); break; case Menu.FIRST + 11: Toast.makeText(MenuByCodingActivity.this, "New 菜单被选择", Toast.LENGTH_LONG).show(); break; } return super.onOptionsItemSelected(item); } }运行程序如下所示:
至此我们第一个MenuAppDemo--硬编码MenusDemo到此,结束。
通过资源文件来构建Menus
1.我们修改activity_menu_by_resource.xml(是MenuByResourceActivity对应的Menu资源文件)文件添加如上硬编码实现的菜单结构
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/fileItem1" android:title="File"> <menu> <group android:id="@+id/group1" > <item android:id="@+id/fileitem2" android:title="New"/> <item android:id="@+id/fileitem3" android:title="Open"/> <item android:id="@+id/fileitem4" android:title="Save"/> <item android:id="@+id/fileitem5" android:title="Exit"/> </group> </menu> </item> <item android:id="@+id/editItem1" android:title="Edit"> <menu> <group android:id="@+id/group2" > <item android:id="@+id/edititem2" android:title="Cut"/> <item android:id="@+id/edititem3" android:title="Copy"/> <item android:id="@+id/edititem4" android:title="Paste"/> </group> </menu> </item> <item android:id="@+id/helpItem1" android:title="Help"> <menu> <group android:id="@+id/group3" > <item android:id="@+id/helpitem2" android:title="About"/> <item android:id="@+id/helpitem3" android:title="Check Update"/> </group> </menu> </item> <item android:id="@+id/Item1" android:title="Menu1"/> <item android:id="@+id/Item2" android:title="Menu2"/> <item android:id="@+id/Item3" android:title="Menu3"/> <item android:id="@+id/Item4" android:title="Menu4"/> </menu>2.我们修改MenuByResourceActivity如下:
package com.jeriffe.android.app; import android.os.Bundle; import android.app.Activity; import android.view.Menu; public class MenuByResourceActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_menu_by_resource); setTitle("资源文件构建菜单"); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_menu_by_resource, menu); return true; } }运行程序,在主界面我们点击第一个Button,如下图左一红色圈圈中的Button,之后的操作和上边的示例:通过硬编码来实现一样。
上下文菜单(Context Menu)
上下文菜单的实现也是很容易的:
构建菜单:重载Activity的onCreateContextMenu方法
注册菜单到指定的View:registerForContextMenu(View view)
重载Activity的onContextItemSelected(MenuItem item),如果我们要实现菜单项的单击事件处理
我们还是通过实例来看如何实现:
我们接着上边的Demo,我们这次只需修改ContextMenuActivity的代码即可
这里我们构建菜单还是上边的Menu资源文件
这里我们是把上下文菜单register到EditText
package com.jeriffe.android.app; import android.app.Activity; import android.os.Bundle; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.MenuItem; import android.view.View; import android.widget.EditText; public class ContextMenuActivity extends Activity { private EditText et; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_context_menu); et = (EditText) findViewById(R.id.editText1); registerForContextMenu(et); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { getMenuInflater().inflate(R.menu.activity_menu_by_resource, menu); } @Override public boolean onContextItemSelected(MenuItem item) { // 这里实现上下文菜单的菜单项单击事件处理 return super.onContextItemSelected(item); } }运行程序,我们点击主界面的第三个Button,如上图左二,之后在EditView里长按鼠标左键,即可看到上下文菜单(如上图右二)。
至此我们的上下文菜单就已经构建完成。
弹出菜单(Popup Menu)
弹出菜单的实例代码在MainActivity里面,运行程序如上图的右一
btnPopupMenu = (Button) findViewById(R.id.popupMenuButton); btnPopupMenu.setOnClickListener(new OnClickListener() { @SuppressLint("NewApi") public void onClick(View v) { PopupMenu popup = new PopupMenu(MainActivity.this, v); MenuInflater inflater = popup.getMenuInflater(); inflater.inflate(R.menu.activity_menu_by_resource, popup.getMenu()); popup.show(); } });
至此我们的3中菜单的演示就已经完成了。
***********************************************************
上边实例都是在Android4.1.2中运行演示;下面是我在不同的Android版本中,选项菜单的不同效果:
Android2.2 WVGA800,这里看到的菜单效果和我的手机(S5830)的效果是一致的。
如果版本是SDK3.0或者SDK3.2(都是平板),那么效果也和SDK4.1.2大致一样。
如果我删除资源文件中的values-v11及values-v14文件(如下所示左一圈中的2个文件夹)SDK版本是4.1.2
如果AVD的Built-In为:WXGA720;那么运行效果如下中间的所示,由于没有Menu硬件按键,我们无法操作。
如果是AVD的Built-In为:WVGA800;那么运行效果如下右一所示,由于我们有Menu硬件按键,我们可以操作菜单,但是效果确实3.0以前的效果。
如果我们保留values-v11及values-v14中的任何一个,那么运行效果和前面讲解的演示效果是一样的。
至于为什么不同版本的效果不同这个是Goolge更新导致:在Version11(SDK3.0)及以后的版本,Google正式宣布取消Android系统中MENU键的使用,也就是基于Android 3.0及以上系统的手机都应没有MENU这一固定按键。所以菜单会出现在界面的右上角,也就是Action Bar的Action overflow中。
我们删除的文件夹是对应V11和V14的,至于为什么删除掉这2个文件夹,效果会和Version11以下的效果一致,我也不是太别清除,还望高手指点