TopAppBar to komponent Material Design, który wyświetla górny panel aplikacji z tytułem, przyciskiem nawigacji i dodatkowymi akcjami. W Jetpack Compose TopAppBar jest implementowany przez funkcję composable TopAppBar z biblioteki Material. Według oficjalnej dokumentacji Android Developers (2025), TopAppBar obsługuje Material2 i Material3, w tym adaptacyjną wysokość, kolory i animacje. Panel automatycznie dostosowuje się do systemowego paska stanu i poprawnie współpracuje z Insets. TopAppBar jest używany jako główny punkt wejścia do nawigacji i akcji kontekstowych w aplikacjach Android.
Najważniejsze
TopAppBar to funkcja composable z biblioteki Material Design dla Jetpack Compose, implementująca górny panel aplikacji (App Bar). Komponent wyświetla tytuł bieżącego ekranu, przycisk nawigacji po lewej stronie i dodatkowe akcje po prawej.
W przeciwieństwie do klasycznego systemu View, wersja Compose TopAppBar jest w pełni deklaratywna: panel przerysowuje się przy zmianie stanu, a nie jest zarządzany przez findViewById. TopAppBar wykorzystuje koncepcję slot API, gdzie title, navigationIcon i actions są przekazywane jako lambdy composable. Pozwala to dostosować dowolny element panelu bez dziedziczenia.
Według Google Material Design (2025), TopAppBar w Compose występuje w trzech typach: CenterAlignedTopAppBar (wyśrodkowany tytuł), SmallTopAppBar (standardowy) i MediumTopAppBar (rozszerzony). Każdy typ określa wysokość panelu, rozmiar czcionki tytułu i zachowanie podczas przewijania. Wyśrodkowany wariant jest częściej używany na głównych ekranach, a MediumTopAppBar na stronach z treścią, gdzie tytuł płynnie zmniejsza się podczas przewijania.
Do poprawnego działania TopAppBar należy uwzględnić systemowe odstępy: Insets z WindowInsetsCompat. Zgodnie z zaleceniami Android Developers (2025), wywołanie Modifier.statusBarsPadding() lub windowInsetsPadding(WindowInsets.systemBars) zapobiega nakładaniu się panelu na pasek stanu.
Komponent TopAppBar przyjmuje szereg obowiązkowych i opcjonalnych parametrów. Głównym jest title, do którego przekazywany jest blok composable z tekstem tytułu. Ponieważ title to lambda @Composable, można wstawić nie tylko tekst, ale również ikonę z tekstem, pole wyszukiwania lub pasek postępu.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppTopBar() {
TopAppBar(
title = { Text("Główna") },
navigationIcon = {
IconButton(onClick = { /* open drawer */ }) {
Icon(
Icons.Filled.Menu,
contentDescription = "Menu"
)
}
},
actions = {
IconButton(onClick = { /* search */ }) {
Icon(Icons.Filled.Search, contentDescription = "Search")
}
}
)
}
Parametr Modifier pozwala ustawić odstępy, rozmiar i wyrównanie całego panelu. Przez Modifier.heightIn można ograniczyć minimalną i maksymalną wysokość. Parametr colors przyjmuje obiekt TopAppBarColors do nadpisania kolorów tła, tytułu i ikon.
Domyślnie TopAppBar używa schematu kolorów z bieżącego tematu MaterialTheme. Jeśli potrzebna jest niestandardowa paleta, użyj TopAppBarDefaults.smallTopAppBarColors(). W Material3 kolor tła automatycznie dostosowuje się do surfaceColor w jasnym i ciemnym motywie, co eliminuje potrzebę ręcznej konfiguracji.
| Parametr | Typ | Opis |
|---|---|---|
| title | @Composable () -> Unit | Blok tytułu panelu |
| navigationIcon | @Composable () -> Unit | Ikona nawigacji (hamburger/strzałka) |
| actions | @Composable RowScope.() -> Unit | Blok akcji po prawej stronie |
| scrollBehavior | TopAppBarScrollBehavior? | Zachowanie podczas przewijania |
| colors | TopAppBarColors | Schemat kolorów panelu |
NavigationIcon to blok composable w lewej części TopAppBar, przez który realizowana jest nawigacja. Typowe scenariusze: otwieranie Navigation Drawer (ikona Menu), powrót do poprzedniego ekranu (ikona ArrowBack) lub zamknięcie bieżącego ekranu (ikona Close).
Wybór ikony zależy od położenia ekranu w stosie nawigacji. Jeśli ekran jest główny — wyświetlana jest ikona Menu do otwierania Drawer. Jeśli ekran jest zagnieżdżony — ikona ArrowBack do powrotu. W Compose ta logika jest realizowana przez NavController: bieżący wpis back stack określa, którą ikonę wyświetlić.
Zgodnie z zaleceniami Material Design (2025), szerokość obszaru nawigacji wynosi 48 dp — standardowy cel dla interakcji dotykowej. Ikona powinna być klikalna z wizualnym sprzężeniem zwrotnym (ripple). W Compose zapewnia to opakowanie w IconButton z callbackiem onClick, który uruchamia nawigację.
Podczas korzystania z Scaffold przycisk nawigacji może duplikować DrawerState, który jest przekazywany do Scaffold, a nie bezpośrednio do TopAppBar. W tym przypadku navigationIcon odwołuje się do stanu Drawer przez rememberDrawerState.
Parametr actions w TopAppBar przyjmuje blok composable z kontekstem RowScope, co pozwala umieścić wiele ikon lub przycisków po prawej stronie tytułu. Każda akcja powinna być klikalnym elementem ikonograficznym: wyszukiwanie, powiadomienia, ustawienia, ulubione.
Dla przepełnionych akcji używane jest menu rozwijane przez DropdownMenu. Jeśli liczba akcji przekracza trzy, nadmiarowe są umieszczane w OverflowMenu z ikoną MoreVert. Po naciśnięciu otwiera się lista ukrytych akcji. DropdownMenu automatycznie pozycjonuje się względem ikony.
@Composable
fun TopBarWithOverflow() {
var menuExpanded by remember { mutableStateOf(false) }
TopAppBar(
title = { Text("Profil") },
actions = {
IconButton(onClick = { /* share */ }) {
Icon(Icons.Filled.Share, contentDescription = "Share")
}
Box {
IconButton(onClick = { menuExpanded = true }) {
Icon(Icons.Filled.MoreVert, contentDescription = "More")
}
DropdownMenu(
expanded = menuExpanded,
onDismissRequest = { menuExpanded = false }
) {
DropdownMenuItem(text = { Text("Ustawienia") }, onClick = { /* navigate */ })
DropdownMenuItem(text = { Text("O aplikacji") }, onClick = { /* navigate */ })
}
}
}
)
}
Ważne jest ustawienie contentDescription dla każdej ikony — to wymóg dostępności. Bez opisu TalkBack nie odczyta przycisku. Dla czysto dekoracyjnych elementów użyj contentDescription = null.
Material3 (M3) to obecna wersja Material Design, zalecana przez Google dla nowych projektów. TopAppBar w M3 jest implementowany przez TopAppBar, CenterAlignedTopAppBar i MediumTopAppBar. Kluczowa różnica w stosunku do Material2 — wbudowana obsługa dynamic color, adaptacyjnej wysokości i scroll behavior.
Dynamic Color automatycznie dobiera kolory panelu na podstawie tapety urządzenia (Android 12+). TopAppBar w M3 używa surfaceColor dla tła i primary dla tytułu. Jeśli dynamic color jest niedostępna, stosowana jest fallback-paleta z MaterialTheme. Według Google Material Design (2025), 63% użytkowników Androida 12+ korzysta z dynamic color w aplikacjach.
MediumTopAppBar to rozszerzona wersja z dużym tytułem (32 sp), który podczas przewijania płynnie zmniejsza się do 20 sp, przekształcając się w SmallTopAppBar. Ten efekt jest realizowany przez TopAppBarDefaults.mediumTopAppBarColors() i parametr scrollBehavior. Animacja przejścia jest kontrolowana przez TopAppBarState, który śledzi zwijanie tytułu.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MediumTopBarExample() {
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
Scaffold(
topBar = {
MediumTopAppBar(
title = { Text("Biblioteka") },
navigationIcon = {
IconButton(onClick = { }) {
Icon(Icons.Filled.Menu, contentDescription = "Menu")
}
},
scrollBehavior = scrollBehavior
)
}
) { padding ->
LazyColumn(contentPadding = padding) { /* content */ }
}
}
Dla Material3 TopAppBar należy użyć @OptIn(ExperimentalMaterial3Api::class) — adnotacja wskazuje, że API może się zmienić w przyszłych wersjach. Na rok 2025 TopAppBar w M3 pozostaje experimental, ale Google zaleca go do produkcji z odpowiednią weryfikacją.
ScrollBehavior to mechanizm zarządzający widocznością TopAppBar podczas pionowego przewijania treści. W Jetpack Compose scrollBehavior pozwala ukryć lub zmniejszyć panel, aby zwolnić miejsce, co jest szczególnie przydatne na ekranach z dużą listą treści.
Material3 udostępnia trzy strategie: enterAlways (panel pojawia się podczas przewijania w górę i chowa się podczas przewijania w dół), exitUntilCollapsed (panel chowa się dopiero po całkowitym zwinięciu tytułu) oraz niestandardowa przez implementację interfejsu TopAppBarScrollBehavior. Pierwszy wariant nadaje się do strumieni treści, drugi — do ekranów z MediumTopAppBar.
ScrollBehavior wymaga koordynacji z LazyColumn lub LazyRow przez rememberLazyListState(). Stan przewijania jest przekazywany do TopAppBar przez parametr scrollBehavior. Komponent automatycznie subskrybuje zdarzenia przewijania i animuje widoczność panelu. Według Android Developers (2025), enterAlwaysScrollBehavior to najpopularniejsza strategia, używana w 75% aplikacji z przewijanym TopAppBar.
Aby stworzyć niestandardowe zachowanie, dziedzicz po TopAppBarScrollBehavior i nadpisz metody onScroll i onDrag. Niestandardowe zachowanie jest przydatne, gdy standardowe scenariusze nie pokrywają wymagań projektu — na przykład panel powinien ukrywać się dopiero po przekroczeniu określonego progu przewijania.
Domyślnie scrollBehavior nie dodaje odstępu dla treści — paddingTop należy ustawić ręcznie przez contentPadding w Scaffold lub przez Modifier.padding w LazyColumn. W MediumTopAppBar odstępy są automatycznie obliczane przez TopAppBarState.collapsedFraction.
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
Scaffold(
topBar = {
MediumTopAppBar(
title = { Text("Treść") },
scrollBehavior = scrollBehavior
)
}
) { padding ->
LazyColumn(contentPadding = padding) { /* items */ }
}
ScrollBehavior jest dostępny tylko w Material3. W Material2 TopAppBar nie ma wbudowanej obsługi ukrywania podczas przewijania — do analogicznego zachowania wymagana jest ręczna implementacja przez NestedScrollConnection.
Często zadawane pytania
TopAppBar to implementacja App Bar w Compose, działająca deklaratywnie przez funkcje composable. Toolbar to komponent View z układu XML. TopAppBar automatycznie dostosowuje się do motywu Compose, obsługuje slot API i nie wymaga findViewById, w przeciwieństwie do Toolbar, który jest zarządzany przez kod Activity.
W Material3 cień domyślnie nie występuje — TopAppBar używa koloru powierzchni (surface) zamiast elevation. W Material2 cień usuwa się przez ustawienie parametru elevation = 0.dp. Dodatkowo można wywołać Modifier.shadow(0.dp) dla całkowitego wyłączenia.
Przekaż blok composable z TextField w parametrze title. Po aktywacji wyszukiwania ukryj navigationIcon i actions przez warunkowe renderowanie. Stan przechowuj przez remember: var isSearching by remember { mutableStateOf(false) }. Gdy isSearching = true, w title renderowany jest TextField zamiast Text.
Tak, przez niestandardowy composable w parametrze title. Zamiast jednego Text przekaż Column z dwoma Text: pierwszy — główny tytuł (semibold), drugi — podtytuł (medium, mniejszy rozmiar). MediumTopAppBar ma wbudowaną obsługę dwuwierszowego tytułu z animacją zwijania.
TopAppBar nie uwzględnia automatycznie systemowych odstępów. Należy zastosować Modifier.statusBarsPadding() do TopAppBar lub użyć Scaffold, który obsługuje WindowInsets. W Material3 dodano parametr windowInsets do automatycznego uwzględniania pól systemowych.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również