Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android之Menu

Android之Menu

編輯:關於Android編程

Android中有各種各樣的菜單,Android的菜單欄(也叫操作欄):ActionBar。先來看下Menu大匯總。
具體可看該網址:https://developer.android.com/guide/topics/ui/menus.html

普通菜單

在Android3.0(API級別11)以下版本,當用戶按“菜單”按鈕時,選項菜單的內容會出現在屏幕底部,如圖 1 所示。打開時,第一個可見部分是圖標菜單,其中包含多達 6 個菜單項。 如果菜單包括 6 個以上項目,則 Android 會將第六項和其余項目放入溢出菜單。用戶可以通過選擇“更多”打開該菜單。
這裡寫圖片描述

在Android3.0及更高版本的系統中,選項菜單中的項目將出現在操作欄中。默認情況下,系統會將所有項目均放入操作溢出菜單中。用戶可以使用操作欄右側的操作溢出菜單圖標(或者,通過按設備“菜單”按鈕(如有))顯示操作溢出菜單。 要支持快速訪問重要操作,您可以將android:showAsAction=”ifRoom” 添加到對應的 元素,從而將幾個項目提升到操作欄中。從 Android 3.0 開始,“菜單”按鈕已棄用(某些設備沒有該按鈕),因此您應改為使用操作欄,來提供對操作和其他選項的訪問。

這裡寫圖片描述

對於上面兩種形式的菜單,示例代碼如下:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.game_menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle item selection
    switch (item.getItemId()) {
        case R.id.new_game:
            newGame();
            return true;
        case R.id.help:
            showHelp();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

關於這種菜單的其他API,具體請自行上網查找。

上下文菜單

基於上面的菜單,Android出了新的菜單,也就是上下文菜單,先看下上下文菜單的效果圖。

提供上下文操作的方法有兩種:

使用浮動上下文菜單。用戶長按(按住)一個聲明支持上下文菜單的視圖時,菜單顯示為菜單項的浮動列表(類似於對話框)。 用戶一次可對一個項目執行上下文操作。(圖中左邊的菜單)使用上下文操作模式。此模式是 ActionMode 的系統實現,它將在屏幕頂部顯示上下文操作欄,其中包括影響所選項的操作項目。當此模式處於活動狀態時,用戶可以同時對多項執行操作(如果應用允許)。(圖中右邊的菜單)

注:上下文操作模式可用於 Android 3.0(API 級別 11)及更高版本的系統,是顯示上下文操作(如果可用)的首選方法。如果應用支持低於 3.0 版本的系統,則應在這些設備上回退到浮動上下文菜單。

創建浮動上下文菜單:

要提供浮動上下文菜單,請執行以下操作:

通過調用 registerForContextMenu(),注冊應與上下文菜單關聯的 View 並將其傳遞給 View。如果 Activity 使用 ListView 或 GridView 且您希望每個項目均提供相同的上下文菜單,請通過將 ListView 或 GridView 傳遞給registerForContextMenu(),為上下文菜單注冊所有項目。

在 Activity 或 Fragment 中實現 onCreateContextMenu() 方法。當注冊後的視圖收到長按事件時,系統將調用您的 onCreateContextMenu() 方法。在此方法中,您通常可通過擴充菜單資源來定義菜單項。例如:

@Override
public void onCreateContextMenu(ContextMenu menu, View v,
                                ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.context_menu, menu);
}

MenuInflater 允許您通過菜單資源擴充上下文菜單。回調方法參數包括用戶所選的 View,以及一個提供有關所選項的附加信息的ContextMenu.ContextMenuInfo 對象。如果 Activity 有多個視圖,每個視圖均提供不同的上下文菜單,則可使用這些參數確定要擴充的上下文菜單。

實現 onContextItemSelected()。
用戶選擇菜單項時,系統將調用此方法,以便您能夠執行適當的操作。 例如:
@Override
public boolean onContextItemSelected(MenuItem item) {
    AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
    switch (item.getItemId()) {
        case R.id.edit:
            editNote(info.id);
            return true;
        case R.id.delete:
            deleteNote(info.id);
            return true;
        default:
            return super.onContextItemSelected(item);
    }
}

getItemId() 方法將查詢所選菜單項的 ID,您應使用 android:id 屬性將此 ID 分配給 XML 中的每個菜單項,如使用 XML 定義菜單部分所示。

成功處理菜單項後,系統將返回 true。如果未處理菜單項,則應將菜單項傳遞給超類實現。 如果 Activity 包括片段,則 Activity 將先收到此回調。 通過在未處理的情況下調用超類,系統將事件逐一傳遞給每個片段中相應的回調方法(按照每個片段的添加順序),直到返回 true 或 false 為止。(Activity 和 android.app.Fragment 的默認實現返回 false,因此您始終應在未處理的情況下調用超類。)
示例代碼如下:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        registerForContextMenu(findViewById(R.id.btn_menu));
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main, menu);
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_home:
                Toast.makeText(MainActivity.this, "menu_home", Toast.LENGTH_SHORT).show();
                break;
            case R.id.menu_recyclerview:
                Toast.makeText(MainActivity.this, "menu_recyclerview", Toast.LENGTH_SHORT).show();
                break;
        }
        return true;
    }
}

使用上下文操作模式

上下文操作模式是 ActionMode 的一種系統實現,它將用戶交互的重點轉到執行上下文操作上。用戶通過選擇項目啟用此模式時,屏幕頂部將出現一個“上下文操作欄”,顯示用戶可對當前所選項執行的操作。
注:上下文操作欄不一定與操作欄相關聯。 盡管表面上看來上下文操作欄取代了操作欄的位置,但事實上二者獨立運行。
為單個視圖啟用上下文操作模式如果希望僅當用戶選擇特定視圖時才調用上下文操作模式,則應:

實現 ActionMode.Callback 接口。在其回調方法中,您既可以為上下文操作欄指定操作,又可以響應操作項目的點擊事件,還可以處理操作模式的其他生命周期事件。當需要顯示操作欄時(例如,用戶長按視圖),請調用 startActionMode()。
示例代碼:
實現 ActionMode.Callback 接口:
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {

    // Called when the action mode is created; startActionMode() was called
    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        // Inflate a menu resource providing context menu items
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.context_menu, menu);
        return true;
    }

    // Called each time the action mode is shown. Always called after onCreateActionMode, but
    // may be called multiple times if the mode is invalidated.
    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false; // Return false if nothing is done
    }

    // Called when the user selects a contextual menu item
    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_share:
                shareCurrentItem();
                mode.finish(); // Action picked, so close the CAB
                return true;
            default:
                return false;
        }
    }

    // Called when the user exits the action mode
    @Override
    public void onDestroyActionMode(ActionMode mode) {
        mActionMode = null;
    }
};

請注意,這些事件回調與選項菜單的回調幾乎完全相同,只是其中每個回調還會傳遞與事件相關聯的 ActionMode 對象。您可以使用 ActionMode API 對 CAB 進行各種更改,例如:使用 setTitle() 和 setSubtitle()(這對指示要選擇多少個項目非常有用)修改標題和副標題。
另請注意,操作模式被銷毀時,上述示例會將 mActionMode 變量設置為 null。在下一步中,您將了解如何初始化該變量,以及保存 Activity 或片段中的成員變量有何作用。

調用 startActionMode() 以便適時啟用上下文操作模式,例如:響應對 View 的長按操作:

someView.setOnLongClickListener(new View.OnLongClickListener() {
    // Called when the user long-clicks on someView
    public boolean onLongClick(View view) {
        if (mActionMode != null) {
            return false;
        }
        // Start the CAB using the ActionMode.Callback defined above
        mActionMode = getActivity().startActionMode(mActionModeCallback);
        view.setSelected(true);
        return true;
    }
});

當您調用 startActionMode() 時,系統將返回已創建的 ActionMode。通過將其保存在成員變量中,您可以更改上下文操作欄來響應其他事件。 在上述示例中, ActionMode 用於在啟動操作模式之前檢查成員是否為空,以確保當 ActionMode 實例已激活時不再重建該實例。
完整的示例代碼:

public class MainActivity extends AppCompatActivity implements android.view.ActionMode.Callback {

    private android.view.ActionMode mActionMode;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.btn_menu_context).setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if (mActionMode != null) {
                    return false;
                }
                mActionMode = startActionMode(MainActivity.this);
                v.setSelected(true);
                return true;
            }
        });
    }

    @Override
    public boolean onCreateActionMode(android.view.ActionMode mode, Menu menu) {
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(android.view.ActionMode mode, Menu menu) {
        return false;
    }

    @Override
    public boolean onActionItemClicked(android.view.ActionMode mode, MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_home:
                Toast.makeText(MainActivity.this, "menu_home", Toast.LENGTH_SHORT).show();
                break;
            case R.id.menu_recyclerview:
                Toast.makeText(MainActivity.this, "menu_recyclerview", Toast.LENGTH_SHORT).show();
                break;
        }
        return true;
    }

    @Override
    public void onDestroyActionMode(android.view.ActionMode mode) {
        mActionMode = null;
    }
}

在 ListView 或 GridView 中啟用批處理上下文操作如果您在 ListView 或 GridView 中有一組項目(或 AbsListView 的其他擴展),且需要允許用戶執行批處理操作,則應:
實現 AbsListView.MultiChoiceModeListener 接口,並使用 setMultiChoiceModeListener() 為視圖組設置該接口。在偵聽器的回調方法中,您既可以為上下文操作欄指定操作,也可以響應操作項目的點擊事件,還可以處理從 ActionMode.Callback 接口繼承的其他回調。 使用 CHOICE_MODE_MULTIPLE_MODAL 參數調用 setChoiceMode()。

例如:

ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {

    @Override
    public void onItemCheckedStateChanged(ActionMode mode, int position,
                                          long id, boolean checked) {
        // Here you can do something when items are selected/de-selected,
        // such as update the title in the CAB
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        // Respond to clicks on the actions in the CAB
        switch (item.getItemId()) {
            case R.id.menu_delete:
                deleteSelectedItems();
                mode.finish(); // Action picked, so close the CAB
                return true;
            default:
                return false;
        }
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        // Inflate the menu for the CAB
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.context, menu);
        return true;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        // Here you can make any necessary updates to the activity when
        // the CAB is removed. By default, selected items are deselected/unchecked.
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        // Here you can perform updates to the CAB due to
        // an invalidate() request
        return false;
    }
});

PopupMenu

PopupMenu 是錨定到 View 的模態菜單。如果空間足夠,它將顯示在定位視圖下方,否則顯示在其上方。
提供類似於 Spinner 且不保留永久選擇的下拉菜單。
注:PopupMenu 在 API 級別 11 及更高版本中可用。

如果使用 XML 定義菜單,則顯示彈出菜單的方法如下:

實例化 PopupMenu 及其構造函數,該函數將提取當前應用的 Context 以及菜單應錨定到的 View。使用 MenuInflater 將菜單資源擴充到 PopupMenu.getMenu() 返回的 Menu 對象中。在 API 級別 14 及更高版本中,您可以改為使用 PopupMenu.inflate()。

例如,以下是一個使用 android:onClick 屬性顯示彈出菜單的按鈕:

稍後,Activity 可按照如下方式顯示彈出菜單:

public void showPopup(View v) {
    PopupMenu popup = new PopupMenu(this, v);
    MenuInflater inflater = popup.getMenuInflater();
    inflater.inflate(R.menu.actions, popup.getMenu());
    popup.show();
}

在 API 級別 14 及更高版本中,您可以將兩行合在一起,使用 PopupMenu.inflate() 擴充菜單。
當用戶選擇項目或觸摸菜單以外的區域時,系統即會清除此菜單。 您可使用 PopupMenu.OnDismissListener 偵聽清除事件。
要在用戶選擇菜單項時執行操作,您必須實現 PopupMenu.OnMenuItemClickListener 接口,並通過調用 setOnMenuItemclickListener() 將其注冊到 PopupMenu。用戶選擇項目時,系統會在接口中調用 onMenuItemClick() 回調。

例如:

public void showMenu(View v) {
    PopupMenu popup = new PopupMenu(this, v);

    // This activity implements OnMenuItemClickListener
    popup.setOnMenuItemClickListener(this);
    popup.inflate(R.menu.actions);
    popup.show();
}

@Override
public boolean onMenuItemClick(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.archive:
            archive(item);
            return true;
        case R.id.delete:
            delete(item);
            return true;
        default:
            return false;
    }
}

效果的話,就是和微信首頁的加號按鈕一樣。
這裡寫圖片描述

   
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved