当前位置: 代码迷 >> Android >> 【攻占Android (13)】Menu 菜单
  详细解决方案

【攻占Android (13)】Menu 菜单

热度:621   发布时间:2016-04-27 23:42:17.0
【攻克Android (13)】Menu 菜单
本文围绕以下三个部分展开:

一、Menu 菜单
二、一个案例
        1、主界面
        2、Options menu 选项菜单
        3、Context menu 上下文菜单
        4、Contextual Action Bar(CAB) 上下文操作栏
        5、Popup menu 弹出菜单

附   代码补充






一、Menu 菜单

        关于菜单:

        3.0 开始 android 取消了实体的菜单按钮,引入了操作栏(Action Bar)

        5.0 将操作栏更名为应用栏(App Bar),有以下四种形式的菜单:

            (1)选项菜单(Options menu)

            (2)上下文菜单(Context menu)

            (3)上下文操作栏(Contextual Action Bar)

            (4)弹出菜单(Popup menu)






二、一个案例

        1、主界面



        (1)activity_main.xml

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"                   xmlns:tools="http://schemas.android.com/tools"                   android:layout_width="match_parent"                   android:layout_height="match_parent"                   android:paddingBottom="@dimen/activity_vertical_margin"                   android:paddingLeft="@dimen/activity_horizontal_margin"                   android:paddingRight="@dimen/activity_horizontal_margin"                   android:paddingTop="@dimen/activity_vertical_margin"                   tools:context=".MainActivity">        <ListView         android:id="@+id/listView"         android:layout_width="match_parent"         android:layout_height="match_parent"/>      </RelativeLayout>


        (2)MainActivity

 package com.android.menu;      import android.app.Activity;   import android.content.Intent;   import android.os.Bundle;   import android.view.View;   import android.widget.AdapterView;   import android.widget.ArrayAdapter;   import android.widget.ListView;         public class MainActivity extends Activity {       private ListView listView;       private String[] data = {"选项菜单(Options menu)", "上下文菜单(Context menu)", "Contextual Action Bar(CAB)", "弹出菜单(Popup menu)"};       private ArrayAdapter<String> adapter;          private Class[] items = {OptionsActivity.class, ContextActivity.class, CabActivity.class, PopupActivity.class};          @Override       protected void onCreate(Bundle savedInstanceState) {           super.onCreate(savedInstanceState);           setContentView(R.layout.activity_main);              // 设置导航图标           getActionBar().setDisplayHomeAsUpEnabled(true);           getActionBar().setHomeAsUpIndicator(R.drawable.ic_menu_white_24dp);              listView = (ListView) findViewById(R.id.listView);           adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.tvItem, data);         listView.setAdapter(adapter);           listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {               @Override               public void onItemClick(AdapterView<?> parent, View view, int position, longid) {                   startActivity(new Intent(getApplicationContext(), items[position]));               }           });       }   }


        2、Options menu 选项菜单



        右上角三个菜单依次是:排序、新增、更多菜单。当点击右上角的三个点的菜单后,会出现下面3项:



        当点击“设置”时,界面弹出“设置操作...”:



        当点击排序菜单时,界面出现排序菜单:



        当点击“隐藏排序”时,排序菜单会隐藏不见:



        当再点击“显示排序”时,排序菜单会出现:



        (1)menu_options.xml

 <menu xmlns:android="http://schemas.android.com/apk/res/android"         xmlns:tools="http://schemas.android.com/tools"         tools:context="com.android.menu.OptionsActivity">        <!--     item 节点:菜单一个选项     id:菜单 id (唯一)     orderInCategory:id索引值 (从小到大加载)     showAsAction:在 应用栏 显示方式     title:菜单文本     -->     <item         android:id="@+id/action_settings"         android:orderInCategory="100"         android:showAsAction="never"         android:title="@string/action_settings"/>        <item         android:id="@+id/action_exit"         android:orderInCategory="101"         android:showAsAction="never"         android:title="@string/action_exit"/>        <!-- id: 标识符 -->     <!-- icon: 图标 -->     <!-- title: (无图标时)显示的文字 -->     <!-- showAsAction: 是否显示在操作栏 -->     <!-- visible: 是否可见,默认 true -->     <!-- enabled: 是否可用,默认 true-->     <!-- orderInCategory: 序号,数值越小越靠前 -->     <item         android:id="@+id/action_new"         android:enabled="true"         android:icon="@drawable/ic_action_new"         android:orderInCategory="102"         android:showAsAction="always"         android:title="@string/action_new"         android:visible="true" />        <!-- checkableBehavior: single(单选)、all(多选)、none(不可选) -->     <!-- checkable: 是否可选 -->     <!-- checked: 是否选中 -->     <item         android:id="@+id/action_sort"         android:icon="@drawable/ic_action_sort_by_size"         android:showAsAction="ifRoom"         android:title="排序">          <menu>         <group            android:id="@+id/group_sort"             android:checkableBehavior="single">           <item               android:id="@+id/action_sort_abc"               android:checked="true"               android:title="字母顺序" />           <item               android:id="@+id/action_sort_desc"               android:title="从大到小" />           <item               android:id="@+id/action_sort_asc"               android:title="从小到大" />           <item               android:id="@+id/action_sort_time"               android:title="最后修改" />        </group>       </menu>     </item>        <item         android:id="@+id/action_hide_sort"         android:showAsAction="never"         android:orderInCategory="99"         android:title="隐藏排序" />   </menu>


        (2)OptionsActivity

 package com.android.menu;     import android.app.Activity;   import android.os.Bundle;   import android.view.Menu;   import android.view.MenuItem;   import android.widget.Toast;      /**   * 选项菜单 Options Menu   */   public class OptionsActivity extends Activity {       private boolean isHideSort = false;          @Override       protected void onCreate(Bundle savedInstanceState) {           super.onCreate(savedInstanceState);           setContentView(R.layout.activity_options);       }          /**       * 1. 创建 选项菜单       *       * @param menu       * @return       */       @Override       public boolean onCreateOptionsMenu(Menu menu) {           // 填充菜单           this.getMenuInflater().inflate(R.menu.menu_options, menu);           return true;       }          /**       * 2. 预处理 选项菜单       *       * @param menu       * @return       */       @Override       public boolean onPrepareOptionsMenu(Menu menu) {           // 修改菜单项的标题           menu.findItem(R.id.action_hide_sort).setTitle(                   isHideSort ? "显示排序" : "隐藏排序");           // 设置菜单是否可见(开始是可见的)           menu.findItem(R.id.action_sort).setVisible(!isHideSort);           // 设置组可见           menu.setGroupVisible(R.id.group_sort, !isHideSort);           // 设置组是否可选           menu.setGroupCheckable(R.id.group_sort, true, true);           // 设置组是否可用           menu.setGroupEnabled(R.id.group_sort, true);              return true;       }          /**       * 3. 选中 选项菜单的事件       *       * @param item       * @return       */       @Override       public boolean onOptionsItemSelected(MenuItem item) {           // 设置菜单项的视觉行为           if (R.id.group_sort == item.getGroupId()) {               // 该组的 checkableBehavior 为单选               item.setChecked(true);               return true;           }              String text = "";           switch (item.getItemId()) {               case R.id.action_settings:                   text = "设置操作...";                   Toast.makeText(this, text, Toast.LENGTH_SHORT).show();                   return true;               case R.id.action_exit:                   // 关闭                   this.finish();                   return true;               case R.id.action_hide_sort:                   isHideSort = !isHideSort;                   // 让菜单重新创建                   // 会调用 onCreateOptionMenu 和 onPrepareOptionsMenu 方法                   invalidateOptionsMenu();                   return true;           }           return super.onOptionsItemSelected(item);       }          /**       * 4. 关闭选项菜单       */       @Override       public void closeOptionsMenu() {           super.closeOptionsMenu();       }   }


        3、Context menu 上下文菜单









        (1)activity_context.xml :

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"                   xmlns:tools="http://schemas.android.com/tools"                   android:layout_width="match_parent"                   android:layout_height="match_parent"                   android:paddingBottom="@dimen/activity_vertical_margin"                   android:paddingLeft="@dimen/activity_horizontal_margin"                   android:paddingRight="@dimen/activity_horizontal_margin"                   android:paddingTop="@dimen/activity_vertical_margin"                   tools:context="com.android.menu.ContextActivity">        <ListView         android:id="@+id/listView_cm"         android:layout_width="match_parent"         android:layout_height="match_parent"/>      </RelativeLayout>


        (2)menu_context.xml :

 <menu xmlns:android="http://schemas.android.com/apk/res/android"         xmlns:tools="http://schemas.android.com/tools"         tools:context="com.android.menu.ContextActivity">            <item android:id="@+id/action_copy"               android:title="复制"/>            <item android:id="@+id/action_paste"               android:title="粘贴"/>            <item android:id="@+id/action_delete"               android:title="删除"/>   </menu>


        (3)ContextActivity :

 package com.android.menu;      import android.app.Activity;   import android.os.Bundle;   import android.view.ContextMenu;   import android.view.Menu;   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 java.util.ArrayList;   import java.util.List;      /**   * 上下文菜单 Context Menu   */   public class ContextActivity extends Activity {       private ListView listView;       private List<String> data = new ArrayList<>();       private ArrayAdapter<String> adapter;          private int position;          @Override       protected void onCreate(Bundle savedInstanceState) {           super.onCreate(savedInstanceState);           setContentView(R.layout.activity_context);              for (int i = 0; i < 30; i++) {               data.add("数据项 " + i);           }              listView = (ListView) findViewById(R.id.listView_cm);           adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data);           listView.setAdapter(adapter);              // 3. 注册上下文菜单,调用 onCreateContextMenu           registerForContextMenu(listView);              // 3.1 注销上下文菜单(一般不会用:既然用了上下文菜单,就不会去注销)           //unregisterForContextMenu(listView);       }          /**       * 1. 创建 上下文菜单       *       * @param menu       * @param v       * @param menuInfo       */       @Override       public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {           this.getMenuInflater().inflate(R.menu.menu_context, menu);              // 设置图标和文本           menu.setHeaderIcon(android.R.drawable.ic_menu_edit);           menu.setHeaderTitle("操作:");              // 菜单信息:targetView、position,id           AdapterView.AdapterContextMenuInfo info =                   (AdapterView.AdapterContextMenuInfo) menuInfo;              // 列表中触发长按事件(弹出菜单)的位置           position = info.position;       }          /**       * 2. 上下文菜单 选项事件       *       * @param item       * @return       */       @Override       public boolean onContextItemSelected(MenuItem item) {           switch (item.getItemId()) {               case R.id.action_copy:                   doOperator("复制");                   break;               case R.id.action_paste:                   doOperator("粘贴");                   break;               case R.id.action_delete:                   doOperator("删除");                   break;           }           return true;       }          private void doOperator(String text) {           // 显示被点击按钮下标的值           Toast.makeText(this, text + " " + data.get(position), Toast.LENGTH_SHORT).show();       }          /**       * 4. 关闭 上下文菜单       *       * @param menu       */       @Override       public void onContextMenuClosed(Menu menu) {           super.onContextMenuClosed(menu);       }   }


        4、Contextual Action Bar(CAB) 上下文操作栏







        (1)activity_cab.xml

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"                   xmlns:tools="http://schemas.android.com/tools"                   android:layout_width="match_parent"                   android:layout_height="match_parent"                   android:paddingBottom="@dimen/activity_vertical_margin"                   android:paddingLeft="@dimen/activity_horizontal_margin"                   android:paddingRight="@dimen/activity_horizontal_margin"                   android:paddingTop="@dimen/activity_vertical_margin"                   tools:context="com.android.menu.CabActivity">        <ListView         android:id="@+id/listView_cab"         android:layout_width="match_parent"         android:layout_height="match_parent"/>      </RelativeLayout>


        (2)menu_cab.xml

 <menu xmlns:android="http://schemas.android.com/apk/res/android"         xmlns:tools="http://schemas.android.com/tools"         tools:context="com.android.menu.CabActivity">            <item android:id="@+id/action_cab_copy"               android:title="复制"/>            <item android:id="@+id/action_cab_delete"               android:title="删除"/>      </menu>


        (3)

 package com.android.menu;      import android.app.Activity;   import android.os.Bundle;   import android.util.Log;   import android.util.SparseBooleanArray;   import android.view.ActionMode;   import android.view.Menu;   import android.view.MenuItem;   import android.widget.AbsListView;   import android.widget.ArrayAdapter;   import android.widget.ListView;      import java.util.ArrayList;         public class CabActivity extends Activity {       private ListView listView;       private ArrayList<String> data = new ArrayList<String>();       private ArrayAdapter<String> adapter;          @Override       protected void onCreate(Bundle savedInstanceState) {           super.onCreate(savedInstanceState);           setContentView(R.layout.activity_cab);              for (int i = 0; i < 30; i++) {               data.add("数据项 " + i);           }              listView = (ListView) findViewById(R.id.listView_cab);              // 模版需要有选中状态(activated)           adapter = new ArrayAdapter<String>(this,                   android.R.layout.simple_list_item_activated_1,                   data);              listView.setAdapter(adapter);              // 设置选择模式           listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);              // 设置多选监听器           listView.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {              @Override               public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {                   // 2. 获得选中的总数                   int count = listView.getCheckedItemCount();                   // 2.1 设置标题 (显示有几个选中了)                   mode.setTitle(String.valueOf(count));               }                  @Override               public boolean onCreateActionMode(ActionMode mode, Menu menu) {                   // 1. 创建菜单                   getMenuInflater().inflate(R.menu.menu_cab, menu);                   return true;               }                  @Override               public boolean onPrepareActionMode(ActionMode mode, Menu menu) {                   return false;               }                  // 3.               @Override               public boolean onActionItemClicked(ActionMode mode, MenuItem item) {                   // 获得选中的多项【稀疏数组】                   SparseBooleanArray array = listView.getCheckedItemPositions();                   switch (item.getItemId()) {                       case R.id.action_cab_copy:                           // {2=true, 4=true, 5=true}................                           Log.v("MENU", array.toString() + "................");                           //适用于有 ID 的数据                           //long[] ids = listView.getCheckedItemIds();                           break;                       case R.id.action_cab_delete:                           for (int i = array.size() - 1; i > -1; i--) {                               // {2=true, 4=true, 5=true}  分割开                               // 获得选中的下标                               int position = array.keyAt(i);                               // 删除数据中的指定元素(之前被选中的元素)                               data.remove(position);                           }                           break;                   }                   //通知视图改变                   adapter.notifyDataSetChanged();                      // 结束CAB模式,调用 onDestoryActionMode 方法                   mode.finish();                   return true;               }                  @Override               public void onDestroyActionMode(ActionMode mode) {                  }           });       }        }


        5、Popup menu 弹出菜单



        (1)activity_popup.xml :

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"                   xmlns:tools="http://schemas.android.com/tools"                   android:layout_width="match_parent"                   android:layout_height="match_parent"                   android:paddingBottom="@dimen/activity_vertical_margin"                   android:paddingLeft="@dimen/activity_horizontal_margin"                   android:paddingRight="@dimen/activity_horizontal_margin"                   android:paddingTop="@dimen/activity_vertical_margin"                   tools:context="com.android.menu.PopupActivity">        <Button         android:id="@+id/button_popupMenu"         style="@android:style/Widget.DeviceDefault.Button.Borderless"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:layout_alignParentEnd="true"         android:layout_alignParentTop="true"         android:drawablePadding="8dp"         android:drawableRight="@drawable/ic_more_vert_grey600_16dp"         android:onClick="onClick"/>      </RelativeLayout>


        (2)menu_popup.xml :

 <menu xmlns:android="http://schemas.android.com/apk/res/android"         xmlns:tools="http://schemas.android.com/tools"         tools:context="com.android.menu.PopupActivity">        <item         android:id="@+id/action_pop_edit"         android:title="编辑"/>        <item         android:id="@+id/action_pop_remove"         android:title="删除"/>      </menu>


        (3)PopupActivity :

 package com.android.menu;      import android.app.Activity;   import android.os.Bundle;   import android.util.Log;   import android.view.MenuItem;   import android.view.View;   import android.widget.PopupMenu;         public class PopupActivity extends Activity {         @Override       protected void onCreate(Bundle savedInstanceState) {           super.onCreate(savedInstanceState);           setContentView(R.layout.activity_popup);       }          public void onClick(View view) {           // 创建弹出菜单           // 参数一:上下文           // 参数二:菜单的锚           PopupMenu menu = new PopupMenu(this, view);              // 加载菜单文件           menu.inflate(R.menu.menu_popup);              // 添加菜单项点击监听器           menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {               @Override               public boolean onMenuItemClick(MenuItem item) {                   switch (item.getItemId()) {                       case R.id.action_pop_edit:                           Log.v("MENU", "修改......");                           break;                       case R.id.action_pop_remove:                           Log.v("MENU", "删除......");                           break;                   }                   return true;               }           });              // 添加菜单消失时的监听器【点击菜单项或其他区域,菜单会消失】           menu.setOnDismissListener(new PopupMenu.OnDismissListener() {               @Override               public void onDismiss(PopupMenu menu) {                  }           });              // 显示菜单           menu.show();       }   }



附   代码补充

        1. style.xml(v21) :

 <?xml version="1.0" encoding="utf-8"?>   <resources>        <style name="AppTheme" parent="android:Theme.Material.Light">       <item name="android:colorPrimaryDark">@android:color/holo_blue_dark</item>       <item name="android:colorPrimary">@android:color/holo_blue_light</item>       <item name="android:navigationBarColor">@android:color/transparent</item>     </style>   </resources>


        2. strings.xml :

 <resources>     <string name="app_name">Menu</string>       <string name="title_activity_options">选项菜单</string>     <string name="title_activity_context">上下文菜单</string>     <string name="title_activity_popup">弹出式菜单</string>     <string name="title_activity_cab">上下文操作栏</string>        <string name="action_settings">设置</string>     <string name="action_exit">退出</string>     <string name="action_new">新建</string>      </resources>


        3. AndroidManifest.xml :

 <?xml version="1.0" encoding="utf-8"?>   <manifest       package="com.android.menu"       xmlns:android="http://schemas.android.com/apk/res/android">        <application         android:allowBackup="true"         android:icon="@mipmap/ic_launcher"         android:label="@string/app_name"         android:theme="@style/AppTheme">       <activity           android:name=".MainActivity"           android:label="@string/app_name">         <intent-filter>           <action android:name="android.intent.action.MAIN"/>              <category android:name="android.intent.category.LAUNCHER"/>         </intent-filter>       </activity>       <activity           android:name=".OptionsActivity"           android:label="@string/title_activity_options"           android:parentActivityName=".MainActivity"/>       <activity           android:name=".ContextActivity"           android:label="@string/title_activity_context"           android:parentActivityName=".MainActivity"/>       <activity           android:name=".CabActivity"           android:label="@string/title_activity_cab"           android:parentActivityName=".MainActivity"/>       <activity           android:name=".PopupActivity"           android:label="@string/title_activity_popup"           android:parentActivityName=".MainActivity"/>     </application>   </manifest>


  相关解决方案