Android java контекстное меню

Урок 15. Контекстное меню

Контекстное меню вызывается в Андроид длительным нажатием на каком-либо экранном компоненте. Обычно оно используется в списках, когда на экран выводится список однородных объектов (например письма в почт.ящике) и, чтобы выполнить действие с одним из этих объектов, мы вызываем контекстное меню для него. Но т.к. списки мы еще не проходили, сделаем пример попроще и будем вызывать контекстное меню для TextView.

Project name: P0151_ContextMenu
Build Target: Android 2.3.3
Application name: ContextMenu
Package name: ru.startandroid.develop.contextmenu
Create Activity: MainActivity

Откроем main.xml и нарисуем там два TextView:

Для первого TextView мы сделаем контекстное меню, с помощью которого будем менять цвет текста. Для второго – будем менять размер текста.

Принцип создания контекстного меню похож на создание обычного меню. Но есть и отличия.

Метод создания onCreateContextMenu вызывается каждый раз перед показом меню. На вход ему передается:

ContextMenu, в который мы будем добавлять пункты
View — элемент экрана, для которого вызвано контекстное меню
ContextMenu.ContextMenuInfo – содержит доп.информацию, когда контекстное меню вызвано для элемента списка. Пока мы это не используем, но, когда будем изучать списки, увидим, что штука полезная.

Метод обработки onContextItemSelected аналогичный методу onOptionsItemSelected для обычного меню. На вход передается MenuItem – пункт меню, который был нажат.

Также нам понадобится третий метод registerForContextMenu. На вход ему передается View и это означает, что для этой View необходимо создавать контекстное меню. Если не выполнить этот метод, контекстное меню для View создаваться не будет.

Давайте кодить, открываем MainActivity.java. Опишем и найдем TextView и укажем, что необходимо создавать для них контекстное меню.

TextView tvColor, tvSize; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.main); tvColor = (TextView) findViewById(R.id.tvColor); tvSize = (TextView) findViewById(R.id.tvSize); // для tvColor и tvSize необходимо создавать контекстное меню registerForContextMenu(tvColor); registerForContextMenu(tvSize); >

Теперь опишем создание контекстных меню. Используем константы для хранения ID пунктов меню.

final int MENU_COLOR_RED = 1; final int MENU_COLOR_GREEN = 2; final int MENU_COLOR_BLUE = 3; final int MENU_SIZE_22 = 4; final int MENU_SIZE_26 = 5; final int MENU_SIZE_30 = 6;
@Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) < // TODO Auto-generated method stub switch (v.getId()) < case R.id.tvColor: menu.add(0, MENU_COLOR_RED, 0, "Red"); menu.add(0, MENU_COLOR_GREEN, 0, "Green"); menu.add(0, MENU_COLOR_BLUE, 0, "Blue"); break; case R.id.tvSize: menu.add(0, MENU_SIZE_22, 0, "22"); menu.add(0, MENU_SIZE_26, 0, "26"); menu.add(0, MENU_SIZE_30, 0, "30"); break; >>

Обратите внимание, что мы по ID определяем View, для которого вызвано контекстное меню и в зависимости от этого создаем определенное меню. Т.е. если контекстное меню вызвано для tvColor, то мы создаем меню с перечислением цветов, а если для tvSizeс размерами шрифта.

В качестве ID пунктов мы использовали константы. Группировку и сортировку не используем, поэтому используем нули в качестве соответствующих параметров.

Можно все сохранить и запустить. При долгом нажатии на TextView должны появляться контекстные меню.

Но нажатие на них ничего не дает, т.к. мы не прописали обработку в методе onContextItemSelected. Давайте пропишем:

@Override public boolean onContextItemSelected(MenuItem item) < // TODO Auto-generated method stub switch (item.getItemId()) < // пункты меню для tvColor case MENU_COLOR_RED: tvColor.setTextColor(Color.RED); tvColor.setText("Text color = red"); break; case MENU_COLOR_GREEN: tvColor.setTextColor(Color.GREEN); tvColor.setText("Text color = green"); break; case MENU_COLOR_BLUE: tvColor.setTextColor(Color.BLUE); tvColor.setText("Text color = blue"); break; // пункты меню для tvSize case MENU_SIZE_22: tvSize.setTextSize(22); tvSize.setText("Text size = 22"); break; case MENU_SIZE_26: tvSize.setTextSize(26); tvSize.setText("Text size = 26"); break; case MENU_SIZE_30: tvSize.setTextSize(30); tvSize.setText("Text size = 30"); break; >return super.onContextItemSelected(item); >

В этом методе мы определяем по ID, какой пункт меню был нажат. И выполняем соответствующие действия: меняем цвет текста для tvColor или размер шрифта для tvSize. Сохраняем, запускаем и проверяем, что контекстные меню теперь реагируют на нажатия и делают то, что от них требуется.

Для расширения кругозора я хотел бы еще кое-что написать по этой теме. Возможно, это покажется пока сложноватым, так что если вдруг будет непонятно, ничего страшного. Итак, мысли вслух.

Мы использовали метод registerForContextMenu (View view) для включения контекстного меню для определенного View. Этот метод принадлежит классу Activity. Я посмотрел исходники этого метода, там написано следующее:

public void registerForContextMenu(View view)

Вспоминаем наш урок по обработчикам и смотрим хелп по методу setOnCreateContextMenuListener (View.OnCreateContextMenuListener l). Получается, что View в качестве обработчика создания контекстного меню использует объект this. В данном случае, этот код в Activity, значит this – это Activity и есть. Т.е. когда View хочет показать контекстное меню, оно обращается к обработчику (Activity), а он уже выполняет свой метод onCreateContextMenu. Т.е. тот же самый принцип, что и при обычном нажатии (Click).

И строка в MainActivity.java:

registerForContextMenu(tvColor);

абсолютно равнозначна этой строке:

tvColor.setOnCreateContextMenuListener(this);

Вообще мы можем создать свой объект, реализующий интерфейс View.OnCreateContextMenuListener и использовать его вместо Activity в качестве обработчика создания контекстного меню.

Не забывайте, что для контекстного меню вы также можете использовать XML-способ, который был рассмотрен в конце прошлого урока. Попробуйте сделать этот же урок, но уже с использованием XML-меню.

public class MainActivity extends Activity < final int MENU_COLOR_RED = 1; final int MENU_COLOR_GREEN = 2; final int MENU_COLOR_BLUE = 3; final int MENU_SIZE_22 = 4; final int MENU_SIZE_26 = 5; final int MENU_SIZE_30 = 6; TextView tvColor, tvSize; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.main); tvColor = (TextView) findViewById(R.id.tvColor); tvSize = (TextView) findViewById(R.id.tvSize); // для tvColor и tvSize необходимо создавать контекстное меню registerForContextMenu(tvColor); registerForContextMenu(tvSize); >@Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) < // TODO Auto-generated method stub switch (v.getId()) < case R.id.tvColor: menu.add(0, MENU_COLOR_RED, 0, "Red"); menu.add(0, MENU_COLOR_GREEN, 0, "Green"); menu.add(0, MENU_COLOR_BLUE, 0, "Blue"); break; case R.id.tvSize: menu.add(0, MENU_SIZE_22, 0, "22"); menu.add(0, MENU_SIZE_26, 0, "26"); menu.add(0, MENU_SIZE_30, 0, "30"); break; >> @Override public boolean onContextItemSelected(MenuItem item) < // TODO Auto-generated method stub switch (item.getItemId()) < // пункты меню для tvColor case MENU_COLOR_RED: tvColor.setTextColor(Color.RED); tvColor.setText("Text color = red"); break; case MENU_COLOR_GREEN: tvColor.setTextColor(Color.GREEN); tvColor.setText("Text color = green"); break; case MENU_COLOR_BLUE: tvColor.setTextColor(Color.BLUE); tvColor.setText("Text color = blue"); break; // пункты меню для tvSize case MENU_SIZE_22: tvSize.setTextSize(22); tvSize.setText("Text size = 22"); break; case MENU_SIZE_26: tvSize.setTextSize(26); tvSize.setText("Text size = 26"); break; case MENU_SIZE_30: tvSize.setTextSize(30); tvSize.setText("Text size = 30"); break; >return super.onContextItemSelected(item); > >

— рисуем экран программно, а не через layout-файл

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

Источник

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

Кроме стандартного меню в 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:

      // добавить в strings.xml Поменять цвет Поменять размер шрифта 

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

 // 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.

Источник

Читайте также:  Special symbols in javascript
Оцените статью