Освой Android играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Контекстное меню и подменю

Программное создание контекстного меню
Контекстное меню через ресурсы

Кроме стандартного меню в Android используется также контекстное меню, вызываемое при нажатии на объект в течение двух-трёх секунд (событие long-press). Также на некоторых моделях устройств контекстное меню можно вызвать при нажатии трекбола или средней кнопки манипулятора D-pad. В отличие от обычного меню, в контекстном меню не поддерживаются значки и быстрые клавиши. Второе важно отличие - контекстное меню применимо к компоненту, а меню к активности. Поэтому в приложении может быть одно меню и несколько контекстных меню, например, у каждого элемента TextView.

Программное создание контекстного меню

Для создания контекстного меню используется метод обратного вызова onCreateContextMenu(). В данный метод можно добавлять пункты меню при помощи методов add(). C помощью метода onContextItemSelected() можно обрабатывать выбор пункта. Но сначала надо зарегистрировать контекстное меню для нужного объекта, например, для TextView при помощи метода registerForContextMenu().


// Kotlin
package ru.alexanderklimov.contextmenu

import android.os.Bundle
import android.view.ContextMenu
import android.view.Menu
import android.view.View
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    companion object {
        const val IDM_OPEN = 101
        const val IDM_SAVE = 102
    }

    private lateinit var textView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)

        textView = findViewById(R.id.textview)
        registerForContextMenu(textView)
    }

    override fun onCreateContextMenu(
        menu: ContextMenu?,
        v: View?,
        menuInfo: ContextMenu.ContextMenuInfo?
    ) {
        super.onCreateContextMenu(menu, v, menuInfo)

        menu?.add(Menu.NONE, IDM_OPEN, Menu.NONE, "Открыть")
        menu?.add(Menu.NONE, IDM_SAVE, Menu.NONE, "Сохранить")
    }
}

// Java package ru.alexanderklimov.contextmenu; import android.os.Bundle; import android.view.ContextMenu; import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { public static final int IDM_OPEN = 101; public static final int IDM_SAVE = 102; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView textView = findViewById(R.id.textView); TextView textView2 = findViewById(R.id.textView2); registerForContextMenu(textView); registerForContextMenu(textView2); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); menu.add(Menu.NONE, IDM_OPEN, Menu.NONE, "Открыть"); menu.add(Menu.NONE, IDM_SAVE, Menu.NONE, "Сохранить"); } }

Если запустить проект, то уже сейчас можно увидеть контекстное меню, которое пока не будет реагировать на выбранные пункты меню.

Контекстное меню

Допишем код для выбранного пункта меню.


// Kotlin
override fun onContextItemSelected(item: MenuItem): Boolean {

    val message: CharSequence = when (item.itemId) {
        IDM_OPEN -> "Выбран пункт Открыть"
        IDM_SAVE -> "Выбран пункт Сохранить"
        else -> return super.onContextItemSelected(item)
    }

    Toast.makeText(this, message, Toast.LENGTH_SHORT).show()

    return true
}

// Java @Override public boolean onContextItemSelected(MenuItem item) { CharSequence message; switch (item.getItemId()) { case IDM_OPEN: message = "Выбран пункт Открыть"; break; case IDM_SAVE: message = "Выбран пункт Сохранить"; break; default: return super.onContextItemSelected(item); } Toast toast = Toast.makeText(this, message, Toast.LENGTH_SHORT); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); return true; }

Контекстное меню через ресурсы

Если вам нужно создать локализованный продукт, то программное добавление пунктов контекстного меню не подойдёт. В таких случаях используется традиционный способ через файл ресурсов, рекомендованный Google.

Создадим XML-файл res/menu/context_menu.xml для меню, а также добавим в разметку ещё один TextView:


<?xml version="1.0" encoding="utf-8"?>
<menu
  xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:id="@+id/change_color"
          android:title="@string/titleChangeColor" />
    <item android:id="@+id/change_textsize"
          android:title="@string/titleChangeTextSize" />
</menu>

// добавить в strings.xml
<string name="titleChangeColor">Поменять цвет</string>
<string name="titleChangeTextSize">Поменять размер шрифта</string>

Добавляем код к существующему.


// Kotlin
override fun onCreateContextMenu(
    menu: ContextMenu?,
    v: View?,
    menuInfo: ContextMenu.ContextMenuInfo?
) {
    super.onCreateContextMenu(menu, v, menuInfo)

    menuInflater.inflate(R.menu.context_menu, menu)
}

override fun onContextItemSelected(item: MenuItem): Boolean {

    when (item.itemId) {
        R.id.change_color -> {
            textView.setBackgroundColor(Color.RED)
            Toast.makeText(this, "Меняем цвет", Toast.LENGTH_SHORT).show()
        }
        R.id.change_textsize -> Toast.makeText(this, "Меняем шрифта", Toast.LENGTH_SHORT)
            .show()
        else -> return super.onContextItemSelected(item)
    }

    return true
}

// Java private TextView textView3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ... textView3 = findViewById(R.id.textView3); registerForContextMenu(textView3); } @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); } @Override public boolean onContextItemSelected(MenuItem item) { CharSequence message; switch (item.getItemId()) { case R.id.change_color: message = "Меняем цвет"; textView3.setBackgroundColor(Color.RED); break; case R.id.change_textsize: message = "Меняем размер шрифта"; textView3.setTextSize(18); break; default: return super.onContextItemSelected(item); } Toast toast = Toast.makeText(this, message, Toast.LENGTH_SHORT); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); return true; }

Мы используем похожий код, как и при создании стандартного меню. В результате получим контекстное меню, созданное из ресурсов. При выборе нужного пункта изменится либо цвет, либо размер шрифта в TextView.

Дополнительное чтение

Создание контекстного меню внутри фрагмента

Реклама