Evgenii Legotckoi
6 марта 2018 г. 13:17

Android. Java vs Qt QML - Урок 005. Создаём контекстное меню

После того, как мы разобрались с тем, как создать меню в Action Bar, добавим контекстное меню к каким-нибудь объектам.

В данном уроке добавим два текстовых поля, которые будут иметь контекстное меню.

  • Контекстное меню первого текстового поля будет изменять цвет и размер текста в первом текстовом поле
  • Контекстное меню второго текстового поля будет просто изменять текст во втором текстовом поле.

Первое контекстное меню будет иметь два подменю, первое будет отвечать за изменение цвета, а второе будет отвечать за изменение размера.

ActionBar в Java активити отключим, чтобы он не мешался.


Внешний вид контекстных меню на Java

Внешний вид контекстных меню на Qt QML

Реализация на Java

activity_main.xml

В Активити создадим два текстовых поля с id:

  • firstTextView
  • secondTextView
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. tools:context="com.evileg.javacontextmenu.MainActivity">
  8.  
  9. <TextView
  10. android:id="@+id/firstTextView"
  11. android:layout_width="wrap_content"
  12. android:layout_height="wrap_content"
  13. android:layout_marginTop="24dp"
  14. android:text="Use context menu to change my color and size"
  15. android:textSize="24sp"
  16. app:layout_constraintEnd_toEndOf="parent"
  17. app:layout_constraintHorizontal_bias="0.5"
  18. app:layout_constraintStart_toStartOf="parent"
  19. app:layout_constraintTop_toTopOf="parent" />
  20.  
  21. <TextView
  22. android:id="@+id/secondTextView"
  23. android:layout_width="wrap_content"
  24. android:layout_height="wrap_content"
  25. android:text="Use context menu to set text"
  26. android:textSize="24sp"
  27. app:layout_constraintBottom_toBottomOf="parent"
  28. app:layout_constraintEnd_toEndOf="parent"
  29. app:layout_constraintHorizontal_bias="0.5"
  30. app:layout_constraintStart_toStartOf="parent"
  31. app:layout_constraintTop_toTopOf="parent" />
  32.  
  33. </android.support.constraint.ConstraintLayout>

MainActivity.java

Контекстное меню в Java будет создаваться через метод onCreateContextMenu.

Данные метод вызывается каждый раз перед вызовом контекстного меню. В данном методе меню заполняется всеми необходимыми пунктами меню в зависимости от того, для какого объекта вызывается данное контекстное меню.

Метод onCreateContextMenu содержит следующие аргументы:

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

Для обработки кликов по пунктам меню будет использоваться метод onContextItemSelected.

Для того, чтобы определить, как из пунктов меню был выбран, потребуется обозначить определённые id для каждого пункта меню, для этого воспользуемся переменными, обозначенными атрибутами final.

Для регистрации элементов интерфейса для обработки контекстного меню воспользуемся методом registerForContextMenu.

  1. package com.evileg.javacontextmenu;
  2.  
  3. import android.app.Activity;
  4. import android.graphics.Color;
  5. import android.os.Bundle;
  6. import android.view.ContextMenu;
  7. import android.view.MenuItem;
  8. import android.view.SubMenu;
  9. import android.view.View;
  10. import android.view.Window;
  11. import android.widget.TextView;
  12.  
  13. public class MainActivity extends Activity {
  14.  
  15. TextView firstTextView;
  16. TextView secondTextView;
  17.  
  18. // Context Menu of firstTextView
  19. final int MENU_COLORS = 1;
  20. final int MENU_SIZES = 2;
  21.  
  22. final int COLOR_RED = 3;
  23. final int COLOR_GREEN = 4;
  24. final int COLOR_BLUE = 5;
  25.  
  26. final int SIZE_24 = 6;
  27. final int SIZE_26 = 7;
  28. final int SIZE_28 = 8;
  29. final int SIZE_30 = 9;
  30.  
  31. // Context Menu of secondTextView
  32. final int TEXT_1 = 10;
  33. final int TEXT_2 = 11;
  34. final int TEXT_3 = 12;
  35.  
  36. @Override
  37. protected void onCreate(Bundle savedInstanceState) {
  38. super.onCreate(savedInstanceState);
  39. this.requestWindowFeature(Window.FEATURE_NO_TITLE);
  40. setContentView(R.layout.activity_main);
  41.  
  42. // Найдём интересующие элементы интерфейса
  43. firstTextView = findViewById(R.id.firstTextView);
  44. secondTextView = findViewById(R.id.secondTextView);
  45.  
  46. // Зарегистрируем их для контекстного меню
  47. registerForContextMenu(firstTextView);
  48. registerForContextMenu(secondTextView);
  49. }
  50.  
  51. // Переопределим метод создания контекстного меню
  52. @Override
  53. public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
  54. {
  55. // В зависимости от того, какое элемент интерфейса был выбран, создадим нужно контекстное меню
  56. switch (v.getId()) {
  57. case R.id.firstTextView:
  58. SubMenu colorsSubMenu = menu.addSubMenu(0, MENU_COLORS, 0, "Colors");
  59. colorsSubMenu.add(0, COLOR_RED, 0, "Red");
  60. colorsSubMenu.add(0, COLOR_GREEN, 0, "Green");
  61. colorsSubMenu.add(0, COLOR_BLUE, 0, "Blue");
  62. SubMenu sizesSubMenu = menu.addSubMenu(1, MENU_SIZES, 0, "Sizes");
  63. sizesSubMenu.add(1, SIZE_24, 0, "24");
  64. sizesSubMenu.add(1, SIZE_26, 0, "26");
  65. sizesSubMenu.add(1, SIZE_28, 0, "28");
  66. sizesSubMenu.add(1, SIZE_30, 0, "30");
  67. break;
  68. case R.id.secondTextView:
  69. menu.add(0, TEXT_1, 0, "Text 1");
  70. menu.add(0, TEXT_2, 0, "Text 2");
  71. menu.add(0, TEXT_3, 0, "Text 3");
  72. break;
  73. }
  74. }
  75.  
  76. // Переопределим метод кликов по контекстному меню
  77. @Override
  78. public boolean onContextItemSelected(MenuItem item)
  79. {
  80. //
  81. switch (item.getItemId())
  82. {
  83. // Обработка пунктов меню первого контекстного меню
  84. case COLOR_RED:
  85. firstTextView.setTextColor(Color.RED);
  86. firstTextView.setText("Red color is setted");
  87. break;
  88. case COLOR_GREEN:
  89. firstTextView.setTextColor(Color.GREEN);
  90. firstTextView.setText("Green color is setted");
  91. break;
  92. case COLOR_BLUE:
  93. firstTextView.setTextColor(Color.BLUE);
  94. firstTextView.setText("Blue color is setted");
  95. break;
  96. case SIZE_24:
  97. firstTextView.setTextSize(24);
  98. firstTextView.setText("Size 24 is setted");
  99. break;
  100. case SIZE_26:
  101. firstTextView.setTextSize(26);
  102. firstTextView.setText("Size 26 is setted");
  103. break;
  104. case SIZE_28:
  105. firstTextView.setTextSize(28);
  106. firstTextView.setText("Size 28 is setted");
  107. break;
  108. case SIZE_30:
  109. firstTextView.setTextSize(30);
  110. firstTextView.setText("Size 30 is setted");
  111. break;
  112. // Обработка пунктов меню второго контекстного меню
  113. case TEXT_1:
  114. secondTextView.setText("Text 1");
  115. break;
  116. case TEXT_2:
  117. secondTextView.setText("Text 2");
  118. break;
  119. case TEXT_3:
  120. secondTextView.setText("Text 3");
  121. break;
  122. }
  123. return super.onContextItemSelected(item);
  124. }
  125. }

Реализация на QML

А вот вёрстка и обработка событий контекстных меню в QML будут реализованы в одном файле main.qml

main.qml

В данном случае для каждого текстового поля будет создан свой объект контекстного меню. Прямо в этих текстовых полях и разместим данное контекстное меню. Для создания меню потребуется соответствующий тип QML Menu.

Меню формируется древовидной структурой из объектов:

  • Menu - если требуется создание подменю
  • Action - действия, которые имеют сигнал triggered и обработчик onTriggered , к слову говоря, при разработке под Desktop , на эти Action можно навешать комбинации горячих клавиш.

В данном случае не понадобится присваивать различные id для пунктов меню, поскольку каждый Action имеет свой обработчик, просто пропишем для каждого свою собственную логику поведения. Обращение к свойствам текстовых полей производится через их id:

  • firstTextView
  • secondTextView
  1. import QtQuick 2.10
  2. import QtQuick.Window 2.10
  3. import QtQuick.Controls 2.3
  4.  
  5. ApplicationWindow {
  6. visible: true
  7. width: 360
  8. height: 520
  9. title: qsTr("QML Context Menu")
  10.  
  11. Text {
  12. id: firstTextView
  13. font.pixelSize: 24
  14. text: qsTr("Use context menu to change my color and size")
  15. wrapMode: Text.Wrap
  16.  
  17. anchors {
  18. top: parent.top
  19. topMargin: 24
  20. left: parent.left
  21. right: parent.right
  22. }
  23.  
  24. // Область клика размещена на весь элемент Text для вызова контекстного меню
  25. MouseArea {
  26. anchors.fill: parent
  27. onPressAndHold: firstContextMenu.open()
  28. }
  29.  
  30. Menu {
  31. id: firstContextMenu
  32. Menu {
  33. title: qsTr("Colors")
  34. Action {
  35. text: qsTr("Red")
  36. onTriggered: {
  37. firstTextView.color = "red"
  38. firstTextView.text = qsTr("Red color is setted")
  39. }
  40. }
  41. Action {
  42. text: qsTr("Green")
  43. onTriggered: {
  44. firstTextView.color = "green"
  45. firstTextView.text = qsTr("Green color is setted")
  46. }
  47. }
  48. Action {
  49. text: qsTr("Blue")
  50. onTriggered: {
  51. firstTextView.color = "blue"
  52. firstTextView.text = qsTr("Blue color is setted")
  53. }
  54. }
  55. }
  56. Menu {
  57. title: qsTr("Sizes")
  58. Action {
  59. text: qsTr("24")
  60. onTriggered: {
  61. firstTextView.font.pixelSize = 24
  62. firstTextView.text = qsTr("Size 24 is setted")
  63. }
  64. }
  65. Action {
  66. text: qsTr("26")
  67. onTriggered: {
  68. firstTextView.font.pixelSize = 26
  69. firstTextView.text = qsTr("Size 26 is setted")
  70. }
  71. }
  72. Action {
  73. text: qsTr("28")
  74. onTriggered: {
  75. firstTextView.font.pixelSize = 28
  76. firstTextView.text = qsTr("Size 28 is setted")
  77. }
  78. }
  79. Action {
  80. text: qsTr("30")
  81. onTriggered: {
  82. firstTextView.font.pixelSize = 30
  83. firstTextView.text = qsTr("Size 30 is setted")
  84. }
  85. }
  86. }
  87. }
  88. }
  89.  
  90. Text {
  91. id: secondTextView
  92. font.pixelSize: 24
  93. text: qsTr("Use context menu to set text")
  94. anchors.centerIn: parent
  95.  
  96. // Область клика размещена на весь элемент Text для вызова контекстного меню
  97. MouseArea {
  98. anchors.fill: parent
  99. onPressAndHold: secondContextMenu.open()
  100. }
  101.  
  102. Menu {
  103. id: secondContextMenu
  104. title: qsTr("Texts")
  105. Action {
  106. text: qsTr("Text 1")
  107. onTriggered: secondTextView.text = text
  108. }
  109. Action {
  110. text: qsTr("Text 2")
  111. onTriggered: secondTextView.text = text
  112. }
  113. Action {
  114. text: qsTr("Text 3")
  115. onTriggered: secondTextView.text = text
  116. }
  117. }
  118. }
  119. }
  120.  

По статье задано0вопрос(ов)

1

Вам это нравится? Поделитесь в социальных сетях!

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
  • Последние комментарии
  • IscanderChe
    12 апреля 2025 г. 17:12
    Добрый день. Спасибо Вам за этот проект и отдельно за ответы на форуме, которые мне очень помогли в некоммерческих пет-проектах. Профессиональным программистом я так и не стал, но узнал мно…
  • AK
    1 апреля 2025 г. 11:41
    Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
  • Evgenii Legotckoi
    9 марта 2025 г. 21:02
    К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
  • VP
    9 марта 2025 г. 16:14
    Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
  • ИМ
    22 ноября 2024 г. 21:51
    Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…