После того, как мы разобрались с тем, как создать меню в Action Bar, добавим контекстное меню к каким-нибудь объектам.
В данном уроке добавим два текстовых поля, которые будут иметь контекстное меню.
- Контекстное меню первого текстового поля будет изменять цвет и размер текста в первом текстовом поле
- Контекстное меню второго текстового поля будет просто изменять текст во втором текстовом поле.
Первое контекстное меню будет иметь два подменю, первое будет отвечать за изменение цвета, а второе будет отвечать за изменение размера.
ActionBar в Java активити отключим, чтобы он не мешался.
Внешний вид контекстных меню на Java
Внешний вид контекстных меню на Qt QML
Реализация на Java
activity_main.xml
В Активити создадим два текстовых поля с id:
- firstTextView
- secondTextView
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.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="com.evileg.javacontextmenu.MainActivity"> <TextView android:id="@+id/firstTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="24dp" android:text="Use context menu to change my color and size" android:textSize="24sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/secondTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Use context menu to set text" android:textSize="24sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </android.support.constraint.ConstraintLayout>
MainActivity.java
Контекстное меню в Java будет создаваться через метод onCreateContextMenu.
Данные метод вызывается каждый раз перед вызовом контекстного меню. В данном методе меню заполняется всеми необходимыми пунктами меню в зависимости от того, для какого объекта вызывается данное контекстное меню.
Метод onCreateContextMenu содержит следующие аргументы:
- ContextMenu , в который добавляются пункты меню
- View - элемент экрана, для которого вызвано контекстное меню
- ContextMenu.ContextMenuInfo – содержит доп.информацию, когда контекстное меню вызывается для элемента списка
Для обработки кликов по пунктам меню будет использоваться метод onContextItemSelected.
Для того, чтобы определить, как из пунктов меню был выбран, потребуется обозначить определённые id для каждого пункта меню, для этого воспользуемся переменными, обозначенными атрибутами final.
Для регистрации элементов интерфейса для обработки контекстного меню воспользуемся методом registerForContextMenu.
package com.evileg.javacontextmenu; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.view.ContextMenu; import android.view.MenuItem; import android.view.SubMenu; import android.view.View; import android.view.Window; import android.widget.TextView; public class MainActivity extends Activity { TextView firstTextView; TextView secondTextView; // Context Menu of firstTextView final int MENU_COLORS = 1; final int MENU_SIZES = 2; final int COLOR_RED = 3; final int COLOR_GREEN = 4; final int COLOR_BLUE = 5; final int SIZE_24 = 6; final int SIZE_26 = 7; final int SIZE_28 = 8; final int SIZE_30 = 9; // Context Menu of secondTextView final int TEXT_1 = 10; final int TEXT_2 = 11; final int TEXT_3 = 12; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); // Найдём интересующие элементы интерфейса firstTextView = findViewById(R.id.firstTextView); secondTextView = findViewById(R.id.secondTextView); // Зарегистрируем их для контекстного меню registerForContextMenu(firstTextView); registerForContextMenu(secondTextView); } // Переопределим метод создания контекстного меню @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { // В зависимости от того, какое элемент интерфейса был выбран, создадим нужно контекстное меню switch (v.getId()) { case R.id.firstTextView: SubMenu colorsSubMenu = menu.addSubMenu(0, MENU_COLORS, 0, "Colors"); colorsSubMenu.add(0, COLOR_RED, 0, "Red"); colorsSubMenu.add(0, COLOR_GREEN, 0, "Green"); colorsSubMenu.add(0, COLOR_BLUE, 0, "Blue"); SubMenu sizesSubMenu = menu.addSubMenu(1, MENU_SIZES, 0, "Sizes"); sizesSubMenu.add(1, SIZE_24, 0, "24"); sizesSubMenu.add(1, SIZE_26, 0, "26"); sizesSubMenu.add(1, SIZE_28, 0, "28"); sizesSubMenu.add(1, SIZE_30, 0, "30"); break; case R.id.secondTextView: menu.add(0, TEXT_1, 0, "Text 1"); menu.add(0, TEXT_2, 0, "Text 2"); menu.add(0, TEXT_3, 0, "Text 3"); break; } } // Переопределим метод кликов по контекстному меню @Override public boolean onContextItemSelected(MenuItem item) { // switch (item.getItemId()) { // Обработка пунктов меню первого контекстного меню case COLOR_RED: firstTextView.setTextColor(Color.RED); firstTextView.setText("Red color is setted"); break; case COLOR_GREEN: firstTextView.setTextColor(Color.GREEN); firstTextView.setText("Green color is setted"); break; case COLOR_BLUE: firstTextView.setTextColor(Color.BLUE); firstTextView.setText("Blue color is setted"); break; case SIZE_24: firstTextView.setTextSize(24); firstTextView.setText("Size 24 is setted"); break; case SIZE_26: firstTextView.setTextSize(26); firstTextView.setText("Size 26 is setted"); break; case SIZE_28: firstTextView.setTextSize(28); firstTextView.setText("Size 28 is setted"); break; case SIZE_30: firstTextView.setTextSize(30); firstTextView.setText("Size 30 is setted"); break; // Обработка пунктов меню второго контекстного меню case TEXT_1: secondTextView.setText("Text 1"); break; case TEXT_2: secondTextView.setText("Text 2"); break; case TEXT_3: secondTextView.setText("Text 3"); break; } return super.onContextItemSelected(item); } }
Реализация на QML
А вот вёрстка и обработка событий контекстных меню в QML будут реализованы в одном файле main.qml
main.qml
В данном случае для каждого текстового поля будет создан свой объект контекстного меню. Прямо в этих текстовых полях и разместим данное контекстное меню. Для создания меню потребуется соответствующий тип QML Menu.
Меню формируется древовидной структурой из объектов:
- Menu - если требуется создание подменю
- Action - действия, которые имеют сигнал triggered и обработчик onTriggered , к слову говоря, при разработке под Desktop , на эти Action можно навешать комбинации горячих клавиш.
В данном случае не понадобится присваивать различные id для пунктов меню, поскольку каждый Action имеет свой обработчик, просто пропишем для каждого свою собственную логику поведения. Обращение к свойствам текстовых полей производится через их id:
- firstTextView
- secondTextView
import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Controls 2.3 ApplicationWindow { visible: true width: 360 height: 520 title: qsTr("QML Context Menu") Text { id: firstTextView font.pixelSize: 24 text: qsTr("Use context menu to change my color and size") wrapMode: Text.Wrap anchors { top: parent.top topMargin: 24 left: parent.left right: parent.right } // Область клика размещена на весь элемент Text для вызова контекстного меню MouseArea { anchors.fill: parent onPressAndHold: firstContextMenu.open() } Menu { id: firstContextMenu Menu { title: qsTr("Colors") Action { text: qsTr("Red") onTriggered: { firstTextView.color = "red" firstTextView.text = qsTr("Red color is setted") } } Action { text: qsTr("Green") onTriggered: { firstTextView.color = "green" firstTextView.text = qsTr("Green color is setted") } } Action { text: qsTr("Blue") onTriggered: { firstTextView.color = "blue" firstTextView.text = qsTr("Blue color is setted") } } } Menu { title: qsTr("Sizes") Action { text: qsTr("24") onTriggered: { firstTextView.font.pixelSize = 24 firstTextView.text = qsTr("Size 24 is setted") } } Action { text: qsTr("26") onTriggered: { firstTextView.font.pixelSize = 26 firstTextView.text = qsTr("Size 26 is setted") } } Action { text: qsTr("28") onTriggered: { firstTextView.font.pixelSize = 28 firstTextView.text = qsTr("Size 28 is setted") } } Action { text: qsTr("30") onTriggered: { firstTextView.font.pixelSize = 30 firstTextView.text = qsTr("Size 30 is setted") } } } } } Text { id: secondTextView font.pixelSize: 24 text: qsTr("Use context menu to set text") anchors.centerIn: parent // Область клика размещена на весь элемент Text для вызова контекстного меню MouseArea { anchors.fill: parent onPressAndHold: secondContextMenu.open() } Menu { id: secondContextMenu title: qsTr("Texts") Action { text: qsTr("Text 1") onTriggered: secondTextView.text = text } Action { text: qsTr("Text 2") onTriggered: secondTextView.text = text } Action { text: qsTr("Text 3") onTriggered: secondTextView.text = text } } } }