Руководство Android ContextMenu

1- Android ContextMenu

Если вы не можете выделить какое-либо пространство пользовательского интерфейса для нужной функции, вы можете использовать  Context Menu (Контекстное меню), Context Menu это плавающее меню (floating menu) отображающее для ответа на долгое нажатие (long press), по умолчанию 500 милисекунд. Context Menu может содержать много  Menu Item и  Sub Menu.
Стандартное долгое нажатие (long press) в Android это 500 милисекунды, вы можете получить данное значение вызывая метод  ViewConfiguration.getLongPressTimeout(). Пользователь может поменять данное значение в Settings, он будет работать со всеми приложениями на устройствами.
Как разработчик, вы не можете настроить другое значение для "период времение долгого нажатия", но вы можете использовать некоторые приемы для симулирования долгого нажатия (long press) с кастомизированным временем и выполнения связанных действий. (Смотрите далее в приложении в конце статьи).
Когда  View регистрируется с событием  Long-Press, система вызовет метод  onCreateContextMenu(), чтобы создать и отобразить  Context Menu.
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    this.button = (Button) this.findViewById(R.id.button_test);

    this.registerForContextMenu(this.button);
}

@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, view, menuInfo);

    menu.setHeaderTitle("Context Menu");

    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.layout_context_menu, menu);
}

// You may not need "Android Resource File" to have a ContextMenu.
// Using Java to create Context Menu.
public void onCreateContextMenu_2(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, view, menuInfo);

    menu.setHeaderTitle("Context Menu");

    // groupId, itemId, order, title
    MenuItem menuItemUpload = menu.add(1, 1, 1, "Upload");
    MenuItem menuItemBookmark = menu.add(2, 2, 2, "Bookmark");  

    // groupId, itemId, order, title
    SubMenu subMenuShare=  menu.addSubMenu(3, 3, 3, "Share");
    subMenuShare.add(4, 31, 1, "Google" );
    subMenuShare.add(5, 32, 2, "Instagram");
}
Когда пользователь нажимает на  Menu Item, вызывается метод  onContextItemSelected().
@Override
public boolean onContextItemSelected(MenuItem item) {

    switch (item.getItemId()) {
        case R.id.menuItem_bookmark:
            Toast.makeText(this, "Bookmark", Toast.LENGTH_SHORT).show();
            break;
        case R.id.menuItem_upload:
            Toast.makeText(this, "Upload", Toast.LENGTH_SHORT).show();
            break;
        case R.id.menuItem_facebook:
            Toast.makeText(this, "Share Facebook", Toast.LENGTH_SHORT).show();
            break;
        case R.id.menuItem_instagram:
            Toast.makeText(this, "Share Instagram", Toast.LENGTH_SHORT).show();
            break;
        default:
            Toast.makeText(this, item.getTitle(), Toast.LENGTH_SHORT).show();
            break;
    }
    return true;
}
Вы можете использовать  XML Android Resource File для дизайна интерфейса  Context Menu. Но  Context Menu приложения обычно довольно прост, поэтому создание  Context Menu полностью из  Java кода тоже является хорошим выбором (Больше примеров ниже).
Примечание: Некоторые атрибуты (attribute) у <item> (Menu Item) не работают, когда они расположены в Context Menu, например:
  • app:showAsAction
  • android:icon  (Not work in Android 3.0+/API 11+)

2- Пример Context Menu

OK, теперь мы выполним пример  Context Menu, просмотрим пример:
На  Android Studio создайте project.
  • Name: ContextMenuExample
  • Package name: org.o7planning.contextmenuexample
Примечание: Начиная с  Android 3.0 (API 11), ContextMenu не поддерживает  Icon, но вы можете скопировать  Icon ниже в папку  drawable для поддержки старых устройств  Android или пропустите этот шаг.
icon_upload.png icon_bookmark.png icon_share.png
Главный интерфейс приложения очень прост, имеется только один  Button, когда пользователь делает долгое нажатие (Long press) на  Button, отобразится  Context Menu.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button_test"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:text="Long Press Me"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    
</androidx.constraintlayout.widget.ConstraintLayout>
На  Android Studio выберите:
  • File > New > Android Resource File
  • File name: layout_context_menu.xml
  • Resource type: Menu
На  Android Studio смоделируйте интерфейс  Context Menu:
Настройте  ID, Title, Icon для  Menu Item:
layout_context_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/menuItem_upload"
        android:icon="@drawable/icon_upload"
        android:title="Upload" />
    <item
        android:id="@+id/menuItem_bookmark"
        android:icon="@drawable/icon_bookmark"
        android:title="Bookmark" />
    <item
        android:id="@+id/menuItem_share"
        android:icon="@drawable/icon_share"
        android:title="Share">
        <menu>
            <item
                android:id="@+id/menuItem_facebook"
                android:title="Facebook" />
            <item
                android:id="@+id/menuItem_instagram"
                android:title="Instagram" />
        </menu>
    </item>
</menu>
MainActivity.java
package org.o7planning.contextmenuexample;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private static final String LOG_TAG = "ContextMenuExample";

    private Button button;

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

        this.button = (Button) this.findViewById(R.id.button_test);

        this.registerForContextMenu(this.button);
    }

    @SuppressLint("RestrictedApi")
    @Override
    public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, view, menuInfo);

        menu.setHeaderTitle("Context Menu");

        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.layout_context_menu, menu);

        // com.android.internal.view.menu.ContextMenuBuilder
        Log.i(LOG_TAG, ">>>>> Menu class: " + menu.getClass().getName());
        // com.android.internal.view.menu.MenuBuilder
        Log.i(LOG_TAG, ">>>>> Menu superclass: " + menu.getClass().getSuperclass().getName());
    }

    // You may not need "Android Resource File" to have a ContextMenu.
    // Using Java to create Context Menu.
    @SuppressLint("RestrictedApi")
    public void onCreateContextMenu_2(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, view, menuInfo);

        menu.setHeaderTitle("Context Menu");

        // groupId, itemId, order, title
        MenuItem menuItemUpload = menu.add(1, 1, 1, "Upload");
        MenuItem menuItemBookmark = menu.add(2, 2, 2, "Bookmark");
        menuItemUpload.setIcon(R.drawable.icon_upload);
        menuItemBookmark.setIcon(R.drawable.icon_bookmark);


        // groupId, itemId, order, title
        SubMenu subMenuShare=  menu.addSubMenu(3, 3, 3, "Share");
        subMenuShare.setIcon(R.drawable.icon_share);

        subMenuShare.add(4, 31, 1, "Google" );
        subMenuShare.add(5, 32, 2, "Instagram");
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            case R.id.menuItem_bookmark:
                Toast.makeText(this, "Bookmark", Toast.LENGTH_SHORT).show();
                break;
            case R.id.menuItem_upload:
                Toast.makeText(this, "Upload", Toast.LENGTH_SHORT).show();
                break;
            case R.id.menuItem_facebook:
                Toast.makeText(this, "Share Facebook", Toast.LENGTH_SHORT).show();
                break;
            case R.id.menuItem_instagram:
                Toast.makeText(this, "Share Instagram", Toast.LENGTH_SHORT).show();
                break;
            default:
                Toast.makeText(this, item.getTitle(), Toast.LENGTH_SHORT).show();
                break;
        }
        return true;
    }
}

3- Приложение: Период времени долгого нажатия

  • TODO