Android筆記(21):UI元件 ContextMenu 快顯功能表

Photo by Caspar Camille Rubin on Unsplash


Android 的 Menu 選單有好幾種,如 ContextMenu、OptionMenu、PopupMenu等,其中 OptionMenu 選項菜單,是透過手機/平板上的 Menu 鍵來啟動(現在的手機/平板大部分都已經取消 Menu 鍵),本篇就來瞭解與實作 ContextMenu。ContextMenu 稱做快顯功能表或上下文功能表,也是一個浮動的菜單選項,類似 Windows 或 Linux 作業系統中,按下滑鼠右鍵的選單。在手機/平板由於沒有右鍵,當使用者在某個元件執行長按或單擊時出現 ContextMenu,這樣的方式不會影響畫面的框架與操作。

[建立 menu 功能表資源檔]

要製作 menu 功能表,需先將功能選項定義在功能表資源檔中,需先在 res 目錄內建立一個 menu 目錄,再建立一個功能表的選單的 XML 檔案,操作的畫面如下:
(1) 首先在 Android Studio 的畫面,對左方的 res 目錄按右鍵,選擇「New」→「Directory」,再輸入目錄名稱為:menu。

(2) 在 menu 目錄按右鍵 → 「New」→「Menu Resource File」

(3) 接著輸入 menu 的 XML 檔檔名。

這樣就完成 XML 檔案的建立,建立的功能表會放置在 res\menu 目錄下。接著要在 XML 檔案中建立選單項目,使用<item></item>標記來建立,一個 menu 檔案中,可以有多個 item 作為選單項目的內容,並可在 item 標記內設置不同屬性,如功能表項目名稱、標題等內容。語法格式如下:
<item
   android:屬性 = "值"> 
</item>
其他有關標記 item 常用的屬性如下表:
XML屬性說明
id設定功能表項目名稱為唯一標識設置ID。
title設定功能表標題。
alphabeticShortcut為功能表項目指定字元快速鍵。
numericShortcut為功能表項目指定數位快速鍵。
icon設定功能表項目圖示。
enabled設定功能表項目是否可用。
checkable設定功能表項目是否可選。
checked功能表項目是否已選中。
visible設定功能表項目是否可見。

若要建立子選單(Submenu),可以在 <item>與 </item>之間再建立一個 <menu></menu>的語法,新增加的 menu 標記中,再增加 item 的標記,如下範例,在「檔案」選項下,再建立兩個子選項「存檔」和「另存為...」。:
    <item
        android:id="@+id/m3"
        android:title="檔案">
        <menu xmlns:android= "http://schemas.android.com/apk/res/android" >
            <item  android:id= "@+id/save"
                android:title= "存檔"  />
            <item  android:id= "@+id/save_as"
                android:title= "另存為..."  />
        </menu>
    </item>


[ContextMenu]

當使用者對元件長按時,彈出的功能表就是 ContextMenu 快顯功能表,如要使用快顯功能表,需先依照上述步驟在資源的功能表目錄內,建立一個 XML 功能表描述檔,接著就要在 java 目錄內找到對應的 MainActivity.java 主程式,進行以下幾個方法的重新定義:

(1) 在 Activity 的 onCreate() 方法中使用 registerForContextMenu() 方法註冊 ContextMenu。
例如為文字方塊元件註冊上下文功能表,當長按該文字方塊時,出現快顯功能表,可以使用以下程式:
TextView tv=(TextView)findViewById(R.id.show);
registerForContextMenu(tv);      //為文字框註冊快顯功能表

(2) 在 MainActivity 中重寫 onCreateContextMenu() 方法。
先建立一個用於解析功能表資源檔的 MenuInflater 物件,然後再使用 inflate() 方法解析一個功能表資源檔,並將解析後的功能表保存在 menu 中,可使用 menu 相關的方法,如設定選單表頭可使用 setHeaderTitle() 方法進行設定,程式碼如下:
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        MenuInflater inflater = new MenuInflater(this);   //產生一個 MenuInflater物件
        inflater.inflate(R.menu.cm_menu, menu);   //解析 menu 選單檔
        menu.setHeaderTitle("請選擇:");     //為選單表頭設置標題
    }

(3) 在 MainActivity 中重寫 onContextItemSelected() 方法,當功能表項目被選擇時,可做出相對應的處理。
例如當功能表項目被選擇時,使用 Toast 顯示一串訊息文字,程式如下:
    public boolean onContextItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.m1:   //在 menu 功能表定義的第一個 item 的名稱
                Toast.makeText(this, "您按下了「關於」...", Toast.LENGTH_LONG).show();
                break;
            case R.id.m2:
                finish();
        }
        return super.onContextItemSelected(item);   // 傳回值
    }

[程式範例]

(1)新建一個模組 Module,在 res 目錄下新增一個 menu 目錄,目錄內建立 menu.xml 檔案,定義內容如下:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/m1"
        android:title="關於快顯功能表選單" />

    <item
        android:id="@+id/m2"
        android:title="結束 APP" />
</menu>

(2) 進入 res/layout 目錄下點選佈局檔 activity_main.xml。將預設的內容刪除,建立 1 個 TextView 文字框,以下是完整 XML 的內容。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tv1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="100sp"
        android:textSize="26sp"
        android:text="長按這裡測試快顯功能表。" />

</RelativeLayout>

(3)在 MainActivity.java 在 onCreate() 方法內,先建立與佈局檔的物件,用 findValueById 連結 TextView 元件,改寫 onCreateContextMenu 取得表單,重寫 onContextItemSelected 根據 item 的 ID 名稱判斷按下的選項,使用 Toast 顯示在畫面上或結束程序。程式碼如下:
package com.example.mycontextmenu;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class cm_MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cm_main);

        TextView tv1 = (TextView) findViewById(R.id.tv1);
        registerForContextMenu(tv1);

        }

    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        MenuInflater inflater = new MenuInflater(this);   //產生一個 MenuInflater物件
        inflater.inflate(R.menu.cm_menu, menu);  //解析 menu 選單檔
        menu.setHeaderTitle("請選擇:");   //為菜單頭設置標題
    }

    public boolean onContextItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.m1:
                Toast.makeText(this, "您按下了「關於快顯功能表選單」...", Toast.LENGTH_LONG).show();
                break;
            case R.id.m2:
                finish();
        }
        return super.onContextItemSelected(item);
    }
}

執行的結果如下:

[參考資料]


Post a Comment

較新的 較舊