Evgenii Legotckoi
06 березня 2018 р. 13:17

Android. Java проти 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

Вам це подобається? Поділіться в соціальних мережах!

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
  • Останні коментарі
  • Evgenii Legotckoi
    16 квітня 2025 р. 17:08
    Благодарю за отзыв. И вам желаю всяческих успехов!
  • IscanderChe
    12 квітня 2025 р. 17:12
    Добрый день. Спасибо Вам за этот проект и отдельно за ответы на форуме, которые мне очень помогли в некоммерческих пет-проектах. Профессиональным программистом я так и не стал, но узнал мно…
  • AK
    01 квітня 2025 р. 11:41
    Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
  • Evgenii Legotckoi
    09 березня 2025 р. 21:02
    К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
  • VP
    09 березня 2025 р. 16:14
    Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…