Після того, як ми розібралися з тим, як створити меню в 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 } } } }