Dolne menu BottomNavigationView
Celem tego projektu jest- Zastosowanie komponentu BottomNavigationView w aplikacjach mobilnych.
- Utworzenie i skonfigurowanie dolnego menu w aplikacji w Android Studio.
- Reagowanie na wybór opcji w dolnym menu i zmieniać zawartość widoku.
Czym jest dolna nawigacja?
BottomNavigationView to element interfejsu użytkownika (UI), który umieszczany jest na dole ekranu aplikacji mobilnej. Zawiera ikonki i etykiety prowadzące do głównych sekcji aplikacji, które są dostępne z każdego miejsca.
Dlaczego warto stosować dolne menu?
- Szybki dostęp do najważniejszych funkcji
- Dolne menu pozwala użytkownikowi przejść do kluczowych ekranów aplikacji bez konieczności cofania się lub otwierania dodatkowego menu (np. hamburgera).
Przykład:
W aplikacji bankowej: Strona główna Przelewy Konto UstawieniaIntuicyjne miejsce nawigacji
Dzięki ergonomii dolnego paska, użytkownik może obsługiwać aplikację jedną ręką, co jest wygodne zwłaszcza na dużych ekranach smartfonów.Zgodność z wytycznymi Material Design
Google promuje dolną nawigację jako element Material Design, szczególnie w przypadku aplikacji z mniej niż 5 głównymi sekcjami.Kiedy nie stosować BottomNavigationView?
- Gdy masz więcej niż 5 sekcji wówczas lepszy będzie Navigation Drawer (hamburger menu).
- Gdy użytkownik musi wykonać zadanie krok po kroku wtedy użyj przyciski Dalej/Wstecz lub TabLayout.
- Gdy menu wymaga zagnieżdżonych podsekcji.
Ile opcji w dolnym menu?
Zalecane:- Minimum: 3 sekcje (np. Home / Info / Settings)
- Maksimum: 5 sekcji
- UI staje się zatłoczone
- Trudniej kliknąć element
- Ikony są zbyt małe, a tekst znika
Przygotowanie głównego widoku aplikacji
Przed utworzeniem projektu otwórz plik bulid.gradle (app) i sprawdź czy dodana jest poniższa zaleznośćWskazówka:
dependencies {
implementation("com.google.android.material:material:1.12.0") // najnowsza wersja
Jak nie ma, to dodaj i wywołaj synchronizację (Sync Now)

Sprawdź czy plik themes.xml używa Theme.MaterialComponents.DayNight. Ustaw jak poniżej
Wskazówka:
parent="Theme.MaterialComponents.DayNight.DarkActionBar"
Wybierz projekt typu Empty Views Activity. Przejdź do widoku budowy głównego układu (layout/ activity_main.xml). Otwórz okno drzewa komponentów (Component Tree) tworzonego układu. Kliknij prawym przyciskiem myszy na głównym elementem widoku (main) i wybierz Cnovert view?

Konwertuj bieżący układ na androidx.coordinatorlayout.widget.CoordinatorLayout

Wybierz Apply.
Główny układ składa się z dwóch kontrolek- FrameLayout
- BottomNavigationView

Kontrolkom ustaw poniższe parametry
Wskazówka:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<FrameLayout
android:id="@+id/Kontener"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/btNawigacja"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Zawartość menu paska nawigacji
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: bottom_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.

Otwieramy plik bottom_menu.xml i wprowadzamy poniższą treść:
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>
Tak utworzony plik XML z zawartością menu nawigacyjnego podpinamy do głównego widoku tworzonej aplikacji poprzez wykorzystanie tego odwołania
app:menu="@menu/bottom_menu"Otwórz plik res/ layout/ activity_main.xml i wprowadź poniższy kod
Wskazówka:
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/btNawigacja"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:menu="@menu/bottom_menu"/>
Wprowadzona zmiana widoczna jest w podglądzie widoku tworzonego układu

Kolorystykę dolnego paska menu można bardzo łatwo zmienić. Na przykład po zdefiniowaniu dodatkowych kolorów i wprowadzeniu tych zmian
Wskazówka:
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/btNawigacja"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:menu="@menu/bottom_menu"
app:labelVisibilityMode="labeled"
android:background="@color/niebieski"
app:itemIconTint="@color/zloty"
app:itemTextColor="@color/zloty"/>
Układ prezentuje się jak poniżej

Tworzenie fragmentów
Aplikacja składa się z trzech prostych fragmentów, 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>
Wczytanie ekranu startowego
Aplikacja w momencie uruchomienia będzie wczytywać główny fragment wraz z widokiem. Wczytanie zrealizujemy funkcją, której parametrem będzie identyfikator wczytywanego fragmentu. To rozwiązani pozwoli wykorzystać funkcje do wczytania pozostałych fragmentów po wybraniu opcji z paska nawigacji.Do pliku MainActivity.kt zaimportuj poniższa bibliotekę
import androidx.fragment.app.FragmentWprowadź ten kod
Wskazówka:
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
}
ladujFragment(GlownyFragment()) // domyślny fragment
}
private fun ladujFragment(fragment: Fragment) {
supportFragmentManager.beginTransaction()
.replace(R.id.Kontener, fragment)
.commit()
}
}
Skompiluj program i sprawdź efekt

Obsługa przycisków menu
Obsługę przycisków dolnego paska nawigacji zrealizujemy w instrukcji when poprzez odczytanie identyfikatora klikniętego elementu. Zmodyfikuj kod do poniższego:Wskazówka:
ladujFragment(GlownyFragment()) // domyślny fragment
val btNawigacji = findViewById<BottomNavigationView>(R.id.btNawigacja)
btNawigacji.setOnItemSelectedListener {
when (it.itemId) {
R.id.nav_home -> ladujFragment(GlownyFragment())
R.id.nav_info -> ladujFragment(InfoFragment())
R.id.nav_settings -> ladujFragment(UstawieniaFragment())
}
true
}
Skompiluj program i sprawdź zachowanie aplikacji

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.fragment.app.Fragment
import com.google.android.material.bottomnavigation.BottomNavigationView
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
}
ladujFragment(GlownyFragment()) // domyślny fragment
val btNawigacji = findViewById<BottomNavigationView>(R.id.btNawigacja)
btNawigacji.setOnItemSelectedListener {
when (it.itemId) {
R.id.nav_home -> ladujFragment(GlownyFragment())
R.id.nav_info -> ladujFragment(InfoFragment())
R.id.nav_settings -> ladujFragment(UstawieniaFragment())
}
true
}
}
private fun ladujFragment(fragment: Fragment) {
supportFragmentManager.beginTransaction()
.replace(R.id.Kontener, fragment)
.commit()
}
}