Menu rozwijane (Overflow)
Celem tego prostego projektu jest:- Zrozumienie działania menu typu overflow.
Dowiesz się, czym jest menu rozwijane (overflow menu), które pojawia się jako ikona z trzema kropkami w prawym górnym rogu aplikacji. Nauczysz się, jak można dodawać do niego opcje (akcje) i kiedy warto z niego korzystać np. wtedy, gdy brakuje miejsca na pasku akcji. - Nauka obsługi opcji menu w onOptionsItemSelected.
Poznasz sposób obsługi kliknięć w elementy menu. Będziesz korzystać z metody onOptionsItemSelected, która umożliwia wykonanie określonych działań, gdy użytkownik wybierze daną opcję z menu (np. zmiana koloru tła, wyświetlenie komunikatu). - Praktyka pracy z MenuInflater i XML menu.
Zobaczysz, jak wczytać menu z pliku XML za pomocą MenuInflater w metodzie onCreateOptionsMenu. Zrozumiesz, jak zapisać strukturę menu w pliku XML (menu_main.xml), co ułatwia czytelność i modyfikację kodu. - Reakcje na kliknięcia w elementy menu zmiana wyglądu i zachowania aplikacji.
Przetestujesz, jak aplikacja może reagować na różne wybory użytkownika z menu np. przez zmianę koloru tła, tekstu, czy pokazanie wiadomości (Toast). Dzięki temu zobaczysz praktyczne zastosowanie menu do sterowania działaniem aplikacji.
Układ widoku
Przygotuj układ widoku aplikacji, który składa się z trzech elementów:- LinearLayout (układ pionowy)
- TextView
- Button

Zawartość menu
Menu w pliku XML to wygodny, przejrzysty i zalecany sposób tworzenia interfejsu użytkownika w aplikacjach Android.Rozdzielenie logiki od wyglądu (zasada separacji)
Plik XML pozwala oddzielić definicję struktury menu (czyli jakie opcje mają się pojawić) od kodu źródłowego aplikacji. Dzięki temu kod w języku Kotlin jest bardziej czytelny i skupia się tylko na tym, co zrobić, gdy opcja zostanie kliknięta.Łatwiejsze modyfikacje i zarządzanie
Zmiany w wyglądzie menu (np. dodanie nowej opcji) można wprowadzić bez modyfikowania kodu w Kotlinie wystarczy edytować plik XML. To przyspiesza pracę i zmniejsza ryzyko błędów.Standaryzacja i zgodność z Androidem
Android umożliwia automatyczne wczytanie menu z pliku XML za pomocą klasy MenuInflater. To sposób zalecany przez dokumentację, zgodny z dobrymi praktykami tworzenia aplikacji.Przygotowanie do skalowalnych aplikacji
Gdy aplikacja rośnie i menu staje się bardziej rozbudowane (np. różne menu dla różnych ekranów), praca z osobnymi plikami XML umożliwia lepszą organizację i ponowne użycie elementów.Dodajemy plik XML, w którym będzie przechowywana zawartość menu. W hierarchii projektu wskaż folder res i z menu prawego przycisku myszki wybierz New/ Android Resources File

W oknie dialogowym podaj nazwę dla pliku XML (tu: menu_main) wybierz typ zasobu (Resource typ przypisz do Menu) jak poniżej.

Prawidłowo wykonane kroki zmieniają układ hierarchii projektu- pojawia się nowy folder wraz z plikiem XML, w którym zapisuje się zawartość menu.

Otwieramy utworzony plik menu_main.xml i wypełniamy go poniższą treścią:
Wskazówka:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Pierwsza opcja menu: zmienia kolor tła -->
<item
android:id="@+id/menu_change_color"
android:title="Zmień kolor tła" />
<!-- Druga opcja menu: wyświetla komunikat Toast -->
<item
android:id="@+id/menu_show_toast"
android:title="Pokaż komunikat" />
<!-- Trzecia opcja menu: przywraca domyślny wygląd -->
<item
android:id="@+id/menu_reset"
android:title="Resetuj widok" />
</menu>
- <menu> to główny element, który zawiera wszystkie opcje menu.
- <item> każda taka sekcja to jedna opcja menu.
- android:id identyfikator, który pozwala rozpoznać, co użytkownik kliknął (obsługa w Kotlinie).
- android:title tekst, który będzie widoczny w menu.
W edytorze Android Studio można przełączyć na podgląd widoku tworzonego menu, które wygląda jak poniżej:

Tak utworzony plik należy wczytać do głównego widoku tworzonej aplikacji przy użyciu klasy MenuInflater, najczęściej w metodzie onCreateOptionsMenu():
Czym jest MenuInflater?
- MenuInflater to specjalna klasa w Androidzie, która pozwala wczytać (czyli "nadmuchać") menu zapisane w pliku XML i wyświetlić je w aplikacji.
- Dzięki niej nie musimy tworzyć menu ręcznie w kodzie Kotlin wystarczy przygotować plik XML z menu.
Do czego służy?
- Zamienia plik XML z menu (np. menu_main.xml) na rzeczywiste opcje menu, które użytkownik widzi w aplikacji.
- Umożliwia programiście szybkie i wygodne wczytanie gotowej struktury menu do aktywności (Activity) lub fragmentu (Fragment).
Jak się jej używa?
- Klasa MenuInflater jest najczęściej używana w metodzie onCreateOptionsMenu():
- R.menu.menu_main wskazuje plik XML z menu, który chcemy wczytać.
Wskazówka:
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
Dlaczego to ważne?
- Użycie MenuInflater to zalecany sposób tworzenia menu jest prosty, czytelny i zgodny z dokumentacją Androida.
- Dzięki temu kod aplikacji jest bardziej uporządkowany osobno definiujemy wygląd menu, a osobno jego działanie.
Podpięcie menu rozwijalnego
UWAGA! Aby menu rozwijalne było wyświetlane w aplikacji, należy upewnić się czy używany jest motyw z ActionBar, np. w res/values/themes/themes.xml:Wskazówka:
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.MenuRozwijaneOverflow" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Customize your light theme here. -->
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
</style>
<style name="Theme.MenuRozwijaneOverflow" parent="Base.Theme.MenuRozwijaneOverflow" />
</resources>
Przejdź do pliku MainActivity.kt dodaj bibliotekę import android.view.Menu
Oraz kod wspomnianej metody wczytującej zawartość menu
Wskazówka:
class MainActivity : AppCompatActivity() {
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
}
Skompiluj aplikację i kliknij w ikonę trzech kropek w górnym prawym rogu ekranu.

Obsługa kliknięcia w opcje menu
Metoda onOptionsItemSelected(item: MenuItem) obsługuje kliknięcia w elementy menu rozwijanego (overflow). Gdy użytkownik wybierze jakąś opcję z menu (np. "Zmień kolor tła"), Android automatycznie wywoła tę metodę i przekaże jej kliknięty element jako argument item.Wykorzystując instrukcję when możemy obsłużyć kolejne akcje związane z wybranym elementem menu.
Do głównego pliku projektu importujemy poniższe klasy
Wskazówka:
import android.view.Menu
import android.view.MenuItem
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import android.widget.Toast
Przygotowujemy zmienną do reprezentacji tła widoku
Wskazówka:
class MainActivity : AppCompatActivity() {
private lateinit var layoutGlowny: LinearLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Pobieramy nasz LinearLayout z layoutu
layoutGlowny = findViewById(R.id.layout_glowny)
}
Wskazówka:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="zloty">#FFC107</color>
<color name="tlo_domyslne">#FFFFFF</color> <!-- kolor biały -->
</resources>
Wykorzystujemy metodę obsługi kliknięcia w opcje menu onOptionsItemSelected(item: MenuItem):Boolean
Przykładowy kod realizujący zdarzenie kliknięcia w opcję menu
Wskazówka:
// Ta metoda obsługuje kliknięcia w opcje menu
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.menu_change_color -> {
// Tutaj np. zmieniamy kolor tła
Toast.makeText(this, "Zmieniono kolor tła", Toast.LENGTH_SHORT).show()
// Zmieniamy kolor tła na złoty pobranuy z zasobów colors.xml
layoutGlowny.setBackgroundColor(ContextCompat.getColor(this, R.color.zloty))
true
}
R.id.menu_show_toast -> {
// Wyświetlamy komunikat Toast
Toast.makeText(this, "Kliknięto opcję Pokaż komunikat", Toast.LENGTH_SHORT).show()
true
}
R.id.menu_reset -> {
// Przykładowa akcja resetowania
Toast.makeText(this, "Zresetowano widok", Toast.LENGTH_SHORT).show()
layoutGlowny.setBackgroundColor(ContextCompat.getColor(this, R.color.tlo_domyslne))
true
}
else -> super.onOptionsItemSelected(item)
}
}
Jak to działa krok po kroku?
1. Sprawdzany jest identyfikator klikniętego elementu za pomocą when (item.itemId).
2. W zależności od tego, co zostało kliknięte:
- Jeśli to "Zmień kolor tła" pokazuje się Toast (komunikat), a w docelowej wersji może też zmienić tło.
- Jeśli to "Pokaż komunikat" wyświetla komunikat Toast.
- Jeśli to "Resetuj widok" również pokazuje Toast (a w pełnej wersji można np. przywrócić wygląd domyślny).
3. Zwracane jest true, co oznacza, że kliknięcie zostało obsłużone.
4. Jeśli żaden przypadek nie pasuje, działanie przekazywane jest do klasy nadrzędnej (super).
Skompiluj aplikacje i sprawdź efekt działania.

Pełny kod pliku MainActivity.kt
Wskazówka:
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
class MainActivity : AppCompatActivity() {
private lateinit var layoutGlowny: LinearLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
// Pobieramy nasz LinearLayout z layoutu
layoutGlowny = findViewById(R.id.layout_glowny)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
// Ta metoda obsługuje kliknięcia w opcje menu
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.menu_change_color -> {
// Tutaj np. zmieniamy kolor tła
Toast.makeText(this, "Zmieniono kolor tła", Toast.LENGTH_SHORT).show()
// Zmieniamy kolor tła na złoty pobranuy z zasobów colors.xml
layoutGlowny.setBackgroundColor(ContextCompat.getColor(this, R.color.zloty))
true
}
R.id.menu_show_toast -> {
// Wyświetlamy komunikat Toast
Toast.makeText(this, "Kliknięto opcję Pokaż komunikat", Toast.LENGTH_SHORT).show()
true
}
R.id.menu_reset -> {
// Przykładowa akcja resetowania
Toast.makeText(this, "Zresetowano widok", Toast.LENGTH_SHORT).show()
layoutGlowny.setBackgroundColor(ContextCompat.getColor(this, R.color.tlo_domyslne))
true
}
else -> super.onOptionsItemSelected(item)
}
}
}