zoukankan      html  css  js  c++  java
  • Android Menu 简析

    简介

      android提供了三种菜单类型,分别为options menu,context menu,sub menu。

      options menu就是通过按home键来显示,context menu需要在view上按上2s后显示。这两种menu都有可以加入子菜单,子菜单不能种不能嵌套子菜单。options menu最多只能在屏幕最下面显示6个菜单选项,称为iconmenu,icon menu不能有checkable选项。多于6的菜单项会以more icon menu来调出,称为expanded menu。options menu通过activity的onCreateOptionsMenu来生成,这个函数只会在menu第一次生成时调用。任何想改变options menu的想法只能在onPrepareOptionsMenu来实现,这个函数会在menu显示前调用。onOptionsItemSelected 用来处理选中的菜单项。

      context menu是跟某个具体的view绑定在一起,在activity种用registerForContextMenu来为某个view注册context menu。context menu在显示前都会调用onCreateContextMenu来生成menu。onContextItemSelected用来处理选中的菜单项。

      android还提供了对菜单项进行分组的功能,可以把相似功能的菜单项分成同一个组,这样就可以通过调用setGroupCheckable,setGroupEnabled,setGroupVisible来设置菜单属性,而无须单独设置。

      Options Menu

    Notepad中使用了options menu和context menu两种菜单。首先来看生成options menu的onCreateOptionsMenu函数。

      menu.add(0, MENU_ITEM_INSERT, 0, R.string.menu_insert)
                    .setShortcut('3', 'a')
                    .setIcon(android.R.drawable.ic_menu_add);

      这是一个标准的插入一个菜单项的方法,菜单项的id为MENU_ITEM_INSERT。有意思的是下面这几句代码:

     Intent intent = new Intent(null, getIntent().getData());
            intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
            menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
                    new ComponentName(this, NotesList.class), null, intent, 0, null);

      这到底有何用处呢?其实这是一种动态菜单技术(也有点像插件机制),若某一个activity,其类型是”android.intent.category.ALTERNATIVE”,数据是”vnd.android.cursor.dir/vnd.google.note”的话,系统就会为这个activity增加一个菜单项。在androidmanfest.xml中查看后发现,没有一个activity符合条件,所以这段代码并没有动态添加出任何一个菜单项。

      为了验证上述分析,我们可以来做一个实验,在androidmanfest.xml中进行修改,看是否会动态生成出菜单项。

      实验一

          首先我们来创建一个新的activity作为目标activity,名为HelloAndroid,没有什么功能,就是显示一个界面。

    public class HelloAndroid extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            this.setContentView(R.layout.main);
        }
    }

      它所对应的布局界面XML文件如下:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
    <TextView  
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" android:id="@+id/TextView01"/>

    <Button android:id="@+id/Button01" android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="@string/txtInfo"></Button>
    </LinearLayout>

    然后修改androidmanfest.xml,加入下面这段配置,让HelloAndroid满足上述两个条件:

        <activity android:name="HelloAndroid" android:label="@string/txtInfo">
                <intent-filter>
                    <action android:name="com.android.notepad.action.HELLO_TEST" />
                    <category android:name="android.intent.category.ALTERNATIVE"/>
                    <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
                </intent-filter>
            </activity>

      好了,运行下试试,哎,还是没有动态菜单项加入呀!怎么回事呢?查看代码后发现,原来是onPrepareOptionsMenu搞的鬼!这个函数在onCreateOptionsMenu之后运行,下面这段代码中,由于Menu.CATEGORY_ALTERNATIVE是指向同一个组,所以把onCreateOptionsMenu中设置的菜单项给覆盖掉了,而由于onPrepareOptionsMenu没有给Menu.CATEGORY_ALTERNATIVE附新值,故Menu.CATEGORY_ALTERNATIVE还是为空。

       Intent intent = new Intent(null, uri);
                intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
                menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0, null, specifics, intent, 0,items);

    好的,那我们暂时把上面这几句给注释掉,当然,也可以不注释这几句,在onCreateOptionsMenu中改groupid号,即将Menu.CATEGORY_ALTERNATIVE改为Menu.first,其他的也行,但注意不要改为menu.none,这样会覆盖掉。

    menu.add(0, MENU_ITEM_INSERT, 0, R.string.menu_insert)
                    .setShortcut('3', 'a')
                    .setIcon(android.R.drawable.ic_menu_add);

      添加的菜单。因为menu.none也为0。运行后就可以看到动态菜单出来了!

    上面这个options menu是在NotesList界面上没有日志列表选中的情况下生成的,若先选中一个日志,然后再点”menu”,则生成的options menu是下面这样的:

    哎,又动态增加了两个菜单项”Edit note”和”Edit title”,这又是如何动态加入的呢?这就是onPrepareOptionsMenu的功劳了。

        Uri uri = ContentUris.withAppendedId(getIntent().getData(), getSelectedItemId());

      首先获取选中的日志(若没有选择,则uri为空)

      Intent[] specifics = new Intent[1];
                specifics[0] = new Intent(Intent.ACTION_EDIT, uri);
                MenuItem[] items = new MenuItem[1];

    然后为选中的日志创建一个intent,操作类型为Intent.ACTION_EDIT,数据为选中日志的URI.于是会为选中的日志创建一个”Edit note”菜单项。

     Intent intent = new Intent(null, uri);
                intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
                menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0, null, specifics, intent, 0,
                        items);

    这几句和上面onCreateOptionsMenu函数中类似,用于动态增加菜单项,若某一个activity,其类型是”android.intent.category.ALTERNATIVE”,数据是”vnd.android.cursor.item/vnd.google.note”的话,系统就会为这个activity增加一个菜单项。在androidmanfest.xml中查看后发现,TitleEditor这个activity符合条件,于是系统就为TitleEditor这个activity动态添加一个菜单项”Edit title”。

    else {
                menu.removeGroup(Menu.CATEGORY_ALTERNATIVE);
            }

      若日志列表为空,则从菜单中删除组号为Menu.CATEGORY_ALTERNATIVE的菜单项,只剩下”Add note”菜单项。

      处理“选中菜单项”事件

      菜单项选中事件的处理非常简单,通过onOptionsItemSelected来完成,这里只是简单地调用 startActivity(new Intent(Intent.ACTION_INSERT, getIntent().getData()));这个intent的操作类型为Intent.ACTION_INSERT,数据为日志列表的URI,即”content:// com.google.provider.NotePad/notes”

         @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
            case MENU_ITEM_INSERT:
                // Launch activity to insert a new item
                startActivity(new Intent(Intent.ACTION_INSERT, getIntent().getData()));
                return true;
            }
            return super.onOptionsItemSelected(item);
        }

      Context Menu

      下面介绍另一种菜单---上下文菜单,这通过重载onCreateContextMenu函数实现。首先确认已经选中了日志列表中的一个日志,若没选择,则直接返回。Cursor指向选中的日志项。

       Cursor cursor = (Cursor) getListAdapter().getItem(info.position);
            if (cursor == null) {
                // For some reason the requested item isn't available, do nothing
                return;
            }

       然后,设置上下文菜单的标题为日志标题

            // Setup the menu header
            menu.setHeaderTitle(cursor.getString(COLUMN_INDEX_TITLE));

          最后为上下文菜单增加一个菜单项

            // Add a menu item to delete the note
            menu.add(0, MENU_ITEM_DELETE, 0, R.string.menu_delete);

       对于上下文菜单项选中的事件处理,是通过重载onContextItemSelected实现的。

            switch (item.getItemId()) {
                case MENU_ITEM_DELETE: {
                    // Delete the note that the context menu is for
                    Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), info.id);
                    getContentResolver().delete(noteUri, null, null);
                    return true;
                }
            }
            return false;
    }

      对于日志的删除,首先调用ContentUris.withAppendedId(getIntent().getData(), info.id);来拼接出待删除日志的URI.然后getContentResolver().delete(noteUri, null, null);调用下层的Content Provider去删除此日志。

      实验二

       来做个简单实验,在上述代码基础上增加一个上下文菜单项。首先在onCreateContextMenu函数中增加一个上下文菜单项:

    menu.add(0,MENU_ITEM_INSERT,0,R.string.menu_insert);

          然后为其在onContextItemSelected函数中增加一个处理过程:

    case MENU_ITEM_INSERT:
                {
                    new AlertDialog.Builder(this).setIcon(R.drawable.app_notes)
                    .setTitle(R.string.app_name).setMessage(R.string.error_message).setPositiveButton(R.string.button_ok, new OnClickListener(){

                        public void onClick(DialogInterface dialog, int which) {
                            // TODO Auto-generated method stub
                            
                        }
       
                    }).show();
                    return true;
                }

          实验结果如下:

    http://news.cnblogs.com/n/78304/

  • 相关阅读:
    51nod 1087 1 10 100 1000(找规律+递推+stl)
    51nod 1082 与7无关的数 (打表预处理)
    51 nod 1080 两个数的平方和
    1015 水仙花数(水题)
    51 nod 1003 阶乘后面0的数量
    51nod 1002 数塔取数问题
    51 nod 1001 数组中和等于K的数对
    51 nod 1081 子段求和
    51nod 1134 最长递增子序列 (O(nlogn)算法)
    51nod 1174 区间中最大的数(RMQ)
  • 原文地址:https://www.cnblogs.com/rollrock/p/1958649.html
Copyright © 2011-2022 走看看