TopAppBar — это компонент Material Design, который отображает верхнюю панель приложения с заголовком, навигационной кнопкой и дополнительными действиями. В Jetpack Compose TopAppBar реализуется через composable-функцию TopAppBar из библиотеки Material. По данным официальной документации Android Developers (2025), TopAppBar поддерживает Material2 и Material3, включая адаптивную высоту, цвета и анимацию. Панель автоматически подстраивается под системный статус-бар и корректно работает с Insets. TopAppBar используется как основная точка входа для навигации и контекстных действий в Android-приложениях.
Главное
TopAppBar — это composable-функция из библиотеки Material Design для Jetpack Compose, реализующая верхнюю панель приложения (App Bar). Компонент отображает заголовок текущего экрана, навигационную кнопку слева и дополнительные действия справа.
В отличие от классической 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(WindоwInsets.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 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также