TopAppBar — це компонент Material Design, який відображає верхню панель застосунку з заголовком, навігаційною кнопкою та додатковими діями. У Jetpack Compose TopAppBar реалізується через composable-функцію TopAppBar з бібліотеки Material. За даними офіційної документації Android Developers (2025), TopAppBar підтримує Material2 і Material3, включаючи адаптивну висоту, кольори та анімацію. Панель автоматично підлаштовується під системний статус-бар і коректно працює з Insets. TopAppBar використовується як основна точка входу для навігації та контекстних дій в Android-застосунках.
Головне
TopAppBar — це composable-функція з бібліотеки Material Design для Jetpack Compose, що реалізує верхню панель застосунку. Компонент відображає заголовок поточного екрана, навігаційну кнопку зліва та додаткові дії справа.
На відміну від класичної View-системи, Compose-версія TopAppBar повністю декларативна: панель перемальовується при зміні стану, а не керується через findViewById. TopAppBar використовує концепцію slot API, де title, navigationIcon та actions передаються як composable-лямбди. Це дозволяє кастомізувати будь-який елемент панелі без успадкування.
За даними Google Material Design (2025), TopAppBar в Compose буває трьох типів: CenterAlignedTopAppBar (центрований заголовок), SmallTopAppBar (стандартний) та MediumTopAppBar (розширений). Кожен тип визначає висоту панелі, розмір шрифту заголовка та поведінку під час скролу. Центрований варіант частіше використовується на головних екранах, а MediumTopAppBar — для сторінок з контентом, де заголовок плавно зменшується при прокручуванні.
Для коректної роботи TopAppBar необхідно враховувати системні відступи: Insets з WindowInsetsCompat. За рекомендацією Android Developers (2025), виклик Modifier.statusBarsPadding() або windowInsetsPadding(WindowInsets.systemBars) запобігає накладанню панелі на статус-бар.
Компонент TopAppBar приймає ряд обов'язкових та опціональних параметрів. Основний — title, куди передається composable-блок з текстом заголовка. Оскільки title — це @Composable лямбда, можна вставити не лише текст, але й іконку з текстом, верстати рядок пошуку або відображати прогрес.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppTopBar() {
TopAppBar(
title = { Text("Main") },
navigationIcon = {
IconButton(onClick = { /* open drawer */ }) {
Icon(
Icons.Filled.Menu,
contentDescription = "Menu"
)
}
},
actions = {
IconButton(onClick = { /* search */ }) {
Icon(Icons.Filled.Search, contentDescription = "Search")
}
}
)
}
Параметр Modifier дозволяє задати відступи, розмір та вирівнювання для всієї панелі. Через Modifier.heightIn можна обмежити мінімальну та максимальну висоту. Параметр colors приймає об'єкт TopAppBarColors для перевизначення кольорів фону, заголовка та іконок.
За замовчуванням TopAppBar використовує кольорову схему з поточної теми MaterialTheme. Якщо потрібна кастомна палітра, використовуйте TopAppBarDefaults.smallTopAppBarColors(). У Material3 фоновий колір автоматично підлаштовується під surfaceColor у світлій та темній темах, що виключає необхідність ручного налаштування.
| Параметр | Тип | Опис |
|---|---|---|
| title | @Composable () -> Unit | Блок заголовка панелі |
| navigationIcon | @Composable () -> Unit | Іконка навігації (гамбургер/стрілка) |
| actions | @Composable RowScope.() -> Unit | Блок екшенів справа |
| scrollBehavior | TopAppBarScrollBehavior? | Поведінка при скролі |
| colors | TopAppBarColors | Кольорова схема панелі |
NavigationIcon — це composable-блок у лівій частині TopAppBar, через який реалізується навігація. Типові сценарії: відкриття Navigation Drawer (іконка Menu), повернення на попередній екран (іконка ArrowBack) або закриття поточного екрана (іконка Close).
Вибір іконки залежить від положення екрана в стеку навігації. Якщо екран кореневий — відображається іконка Menu для відкриття Drawer. Якщо екран вкладений — іконка ArrowBack для повернення. У Compose ця логіка реалізується через NavController: поточний back stack entry визначає, яку іконку показувати.
За рекомендацією Material Design (2025), ширина навігаційної області становить 48 dp — стандартний таргет для touch-взаємодії. Іконка має бути клікабельною з візуальним зворотним зв'язком (ripple). У Compose це забезпечується обгорткою в IconButton з onClick-колбеком, який запускає навігацію.
При використанні Scaffold навігаційна кнопка може дублювати DrawerState, який передається в Scaffold, а не в TopAppBar безпосередньо. У цьому випадку navigationIcon посилається на стан Drawer через rememberDrawerState.
Параметр actions у TopAppBar приймає composable-блок з контекстом RowScope, що дозволяє розміщувати кілька іконок або кнопок справа від заголовка. Кожен action має бути клікабельним іконографічним елементом: пошук, сповіщення, налаштування, обране.
Для переповнених екшенів використовується випадне меню через DropdownMenu. Якщо кількість дій перевищує три, зайві поміщаються в OverflowMenu з іконкою MoreVert. При натисканні відкривається список прихованих екшенів. DropdownMenu автоматично позиціонується відносно іконки.
@Composable
fun TopBarWithOverflow() {
var menuExpanded by remember { mutableStateOf(false) }
TopAppBar(
title = { Text("Profile") },
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("Settings") }, onClick = { /* navigate */ })
DropdownMenuItem(text = { Text("About") }, onClick = { /* navigate */ })
}
}
}
)
}
Важно задати contentDescription для кожної іконки — це вимога accessibility. Без опису TalkBack не озвучить кнопку. Для суто декоративних елементів використовуйте contentDescription = null.
Material3 (M3) — поточна версія Material Design, рекомендована Google для нових проєктів. TopAppBar в M3 реалізований через TopAppBar, CenterAlignedTopAppBar та MediumTopAppBar. Ключова відмінність від Material2 — вбудована підтримка dynamic color, адаптивної висоти та scroll behavior.
Dynamic Color автоматично підбирає кольори панелі на основі шпалер пристрою (Android 12+). TopAppBar в M3 використовує surfaceColor для фону та primary для заголовка. Якщо dynamic color недоступна, застосовується fallback-палітра з MaterialTheme. За даними Google Material Design (2025), 63% користувачів Android 12+ використовують dynamic color в застосунках.
MediumTopAppBar — розширений варіант з великим заголовком (32 sp), який під час прокручування плавно зменшується до 20 sp, перетворюючись на SmallTopAppBar. Цей ефект реалізується через TopAppBarDefaults.mediumTopAppBarColors() та параметр scrollBehavior. Анімація переходу контролюється через TopAppBarState, який відстежує колапс заголовка.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MediumTopBarExample() {
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
Scaffold(
topBar = {
MediumTopAppBar(
title = { Text("Library") },
navigationIcon = {
IconButton(onClick = { }) {
Icon(Icons.Filled.Menu, contentDescription = "Menu")
}
},
scrollBehavior = scrollBehavior
)
}
) { padding ->
LazyColumn(contentPadding = padding) { /* content */ }
}
}
Для Material3 TopAppBar обов'язково використовувати @OptIn(ExperimentalMaterial3Api::class) — анотація вказує, що API може змінитися в майбутніх версіях. На момент 2025 року TopAppBar в M3 залишається experimental, але Google рекомендує його для продакшену з відповідною перевіркою.
ScrollBehavior — механізм, що керує видимістю TopAppBar при вертикальному прокручуванні контенту. У Jetpack Compose scrollBehavior дозволяє приховати або зменшити панель для звільнення місця, що особливо корисно на екранах з великим списком контенту.
Material3 надає три стратегії: enterAlways (панель з'являється при скролі вгору і ховається при скролі вниз), exitUntilCollapsed (панель ховається тільки після повного колапсу заголовка) та кастомна через реалізацію інтерфейсу TopAppBarScrollBehavior. Перший варіант підходить для стрічок контенту, другий — для екранів з MediumTopAppBar.
ScrollBehavior вимагає координації з LazyColumn або LazyRow через rememberLazyListState(). Стан скролу передається в TopAppBar через параметр scrollBehavior. Компонент автоматично підписується на події скролу та анімує видимість панелі. За даними Android Developers (2025), enterAlwaysScrollBehavior — найпопулярніша стратегія, що використовується в 75% застосунків з прокручуваним TopAppBar.
Для створення кастомної поведінки успадковуйтесь від TopAppBarScrollBehavior та перевизначте методи onScroll і onDrag. Кастомний behaviour корисний, коли стандартні сценарії не покривають вимоги дизайну — наприклад, панель має ховатися тільки після перевищення певного порогу скролу.
За замовчуванням scrollBehavior не додає відступ для контенту — paddingTop потрібно задавати вручну через contentPadding в Scaffold або через Modifier.padding в LazyColumn. У MediumTopAppBar відступи автоматично розраховуються через TopAppBarState.collapsedFraction.
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
Scaffold(
topBar = {
MediumTopAppBar(
title = { Text("Content") },
scrollBehavior = scrollBehavior
)
}
) { padding ->
LazyColumn(contentPadding = padding) { /* items */ }
}
ScrollBehavior доступний тільки в Material3. У Material2 TopAppBar не має вбудованої підтримки приховування при скролі — для аналогічної поведінки потрібна ручна реалізація через NestedScrollConnection.
Часті запитання
TopAppBar — це Compose-реалізація App Bar, що працює декларативно через composable-функції. Toolbar — View-компонент з XML-верстки. TopAppBar автоматично підлаштовується під тему Compose, підтримує slot API та не потребує findViewById, на відміну від Toolbar, який керується через код Activity.
У Material3 тінь відсутня за замовчуванням — TopAppBar використовує поверхневий колір (surface) замість elevation. У Material2 тінь прибирається встановленням параметра elevation = 0.dp. Додатково можна викликати Modifier.shadow(0.dp) для повного відключення.
Передайте composable-блок з TextField в параметр title. При активації пошуку сховайте navigationIcon та actions через умовний рендеринг. Стан зберігайте через remember: var isSearching by remember { mutableStateOf(false) }. При isSearching = true в title рендериться TextField замість Text.
Так, через кастомний composable в параметр title. Замість одного Text передайте Column з двома Text: перший — основний заголовок (semibold), другий — підзаголовок (medium, менший розмір). MediumTopAppBar має вбудовану підтримку дворядкового заголовка з анімацією колапсу.
TopAppBar не враховує системні відступи автоматично. Необхідно застосувати Modifier.statusBarsPadding() до TopAppBar або використовувати Scaffold, який обробляє WindowInsets. У Material3 додано параметр windowInsets для автоматичного врахування системних полів.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також