Boczne menu- Navigation Drawer
Boczne menu (Navigation Drawer) to popularny element interfejsu użytkownika w aplikacjach mobilnych, który umożliwia dostęp do głównych sekcji aplikacji poprzez wysuwany panel z lewej (lub rzadziej prawej) krawędzi ekranu. Zwykle jest reprezentowane przez ikonę tzw. hamburgera (trzy poziome kreski) znajdującą się w górnym pasku aplikacji.
Ten typ menu stosuje się, gdy chcemy udostępnić użytkownikowi szybki dostęp do wielu funkcji aplikacji, ale jednocześnie zachować porządek i nie przeładowywać głównego widoku. Navigation Drawer pozwala ukryć rzadziej używane opcje, a jednocześnie umożliwia ich wygodne otwarcie w dowolnym momencie. Stosuje się go często w aplikacjach wielosekcyjnych (np. Gmail, YouTube), ponieważ zapewnia przejrzystą i intuicyjną nawigację.
Z przedstawionych treści dowiesz się:- czym jest Navigation Drawer i jakie pełni funkcje w aplikacji mobilnej,
- jakie komponenty tworzą strukturę DrawerLayout.
- utworzyć projekt z DrawerLayout w Android Studio,
- zbudować XML layout zawierający NavigationView,
- dodać nagłówek i elementy menu do Navigation Drawer,
- zaimplementować reakcję na wybór opcji w menu.
Główny układ widoku aplikacji
Utworzenie nowego projektu rozpocznij od wybrania Empty Activity. W widoku hierarchii projektu wybierz res/ layout/ activity_main.xml. Przejdź do okna Component Tree kliknij prawym przyciskiem myszki na elemencie main i przekonwertuj go na androidx.drawerlayout.widget.DrawerLayout. Patrz poniższa ilustracja

Usuń standardową kontrolkę TextView (Hello Word) i osadź kontrolki:
- FrameLayout
- NavigationView

Kontrolkom przypisz identyfikatory (id/kontener, id/nawigator). Zawartość pliku activity_main.xml podana jest poniżej
Wskazówka:
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- Zawartość główna -->
<FrameLayout
android:id="@+id/kontener"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- Navigation Drawer -->
<com.google.android.material.navigation.NavigationView
android:id="@+id/nawigator"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
/>
</androidx.drawerlayout.widget.DrawerLayout>
Dodanie pliku menu i nagłówka menu
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: boczne_menu) wybierz typ zasobu (Resource typ przypisz do Menu) jak poniżej.

W tworzonym menu skorzystamy z graficznych ikon zapisanych w formacie wektorowym. Ikony należy powiązać tematycznie z opcjami menu, którymi będzie widok główny, widok informacyjny i widok ustawień Wybierzemy trzy standardowe ikony klikając prawym przyciskiem myszki w res/ drawable/ New/ Vector Assets

Prawidłowo osadzone pliki XML ikon pojawią się w strukturze hierarchii projektu.

Przechodzimy do pliku boczne_menu.xml osadzamy w nim trzy kontrolki typu Item, przypisujemy im identyfikator, tytuł i ikonę. Zawartość pliku boczne_menu.xml
Wskazówka:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/nav_home"
android:icon="@drawable/ic_home_24"
android:title="Start" />
<item
android:id="@+id/nav_info"
android:icon="@drawable/ic_info_24"
android:title="Informacje" />
<item
android:id="@+id/nav_settings"
android:icon="@drawable/ic_settings_24"
android:title="Ustawienia" />
</menu>
Nagłówek menu to osobny układ (layout) oparty na kontrolce LinearLayout (vertical). Układ ten zapisany jest w pliku XML w folderze res/ layout. Dodajemy taki zasób do hierarchii projektu.

Proponowana zawartość pliku XML nagłówka menu pokazana jest poniżej
Wskazówka:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:padding="16dp"
android:background="@color/czerwony"
android:layout_width="match_parent"
android:layout_height="96dp"
android:gravity="bottom">
<TextView
android:id="@+id/header_text"
android:text="Menu boczne- cześć:)"
android:textColor="@android:color/white"
android:textSize="18sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Utworzone pliki zawartości elementów menu oraz nagłówka należy podpiąć do kontrolki NavigationView zapisanej w pliku activity_main.xml. Otwórz ten plik i wprowadź poniższe zmiany
Wskazówka:
<!-- Navigation Drawer -->
<com.google.android.material.navigation.NavigationView
android:id="@+id/nawigator"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="@menu/boczne_menu"
app:headerLayout="@layout/naglowek_menu"
/>
Skompiluj program i sprawdź efekt działania. Menu boczne wywołasz kursorem myszki przesuwając od lewego boku ekranu emulatora w prawa stronę.

Obsługa menu
Menu obsłużymy na tych samych zasadach co w temacie Dolne menu BottomNavigationView. Reakcją na kliknięcie będzie przełączenie widoku na wybrany fragment.
Dodajemy trzy fragmenty, które są ładowane do kontenera głównego widoku. Fragmenty to GlownyFragment, InfoFragment i UstawieniaFragment. Ich użycie wymaga utworzenie trzech klas z widokami.
Kliknij prawym przyciskiem myszki w hierarchii projektu w folderze w którym przechowywany jest plik MainActivity.kt i wybierz jak na poniższej ilustracji

W oknie dialogowym wprowadź nazwę tworzonego fragmentu. Pod wprowadzoną nazwą zostanie utworzona klasa odpowiedzialna za obsługę danego fragmentu tworzonej aplikacji oraz plik układu widoku (Layout).

Prawidłowo wykonane czynności utworzą trzy pliki klas i trzy pliki widoków.

W plikach widoków utworzonych fragmentów wprowadzamy dowolny element, który pozwoli je w łatwy sposób rozróżnić. Poniżej jest to TextView
Wskazówka:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".GlownyFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Ekran startowy"
android:gravity="center"
android:textSize="24sp"/>
</FrameLayout>
Ładowanie fragmentów
Każdy z fragmentów wczytamy uniwersalna funkcja z jednym parametrem, którym jest identyfikator wczytywanego fragmentu.
Wskazówka:
private fun ladujFragment(fragment: Fragment) {
supportFragmentManager.beginTransaction()
.replace(R.id.kontener, fragment)
.commit()
}
Obsługę kliknięcia w element menu wykonamy przy pomocy instrukcji when w metodzie setNavigationItemSelectedListener. Modyfikujemy zawartość funkcji onCreate(
Wskazówka:
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
}
val btNawigator = findViewById<NavigationView>(R.id.nawigator)
ladujFragment(GlownyFragment()) // domyślny fragment
btNawigator.setNavigationItemSelectedListener {
when (it.itemId) {
R.id.nav_home -> ladujFragment(GlownyFragment())
R.id.nav_info -> ladujFragment(InfoFragment())
R.id.nav_settings -> ladujFragment(UstawieniaFragment())
}
// Zamknij szufladę po kliknięciu
val szuflada = findViewById<DrawerLayout>(R.id.main)
szuflada.closeDrawers()
true
}
}
Skompiluj program i sprawdź efekt działania. Poniżej wysunięcie szuflady menu bocznego z aktywnym kliknięciem

I moment chowania szuflady po przełączeniu fragmentu na informacyjny

Pełny kod pliku MainActivity.kt
Wskazówka:
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.drawerlayout.widget.DrawerLayout
import androidx.fragment.app.Fragment
import com.google.android.material.navigation.NavigationView
class MainActivity : AppCompatActivity() {
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
}
val btNawigator = findViewById<NavigationView>(R.id.nawigator)
ladujFragment(GlownyFragment()) // domyślny fragment
btNawigator.setNavigationItemSelectedListener {
when (it.itemId) {
R.id.nav_home -> ladujFragment(GlownyFragment())
R.id.nav_info -> ladujFragment(InfoFragment())
R.id.nav_settings -> ladujFragment(UstawieniaFragment())
}
// Zamknij szufladę po kliknięciu
val szuflada = findViewById<DrawerLayout>(R.id.main)
szuflada.closeDrawers()
true
}
}
private fun ladujFragment(fragment: Fragment) {
supportFragmentManager.beginTransaction()
.replace(R.id.kontener, fragment)
.commit()
}
}