Нижняя навигация и вкладки
Реализуйте навигацию по разделам с помощью BottomNavigationView, подключённого к NavController, а также вкладки с пролистыванием через TabLayout, ViewPager2 и TabLayoutMediator.
«Нижняя навигация и вкладки» — бесплатный урок Android Academy на CoddyKit. Это урок 5 из 5. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Android Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Android Academy содержит 5 уроков всего.
Шаблоны навигации
Два распространённых шаблона навигации верхнего уровня в приложениях Android:
- Нижняя навигация — для 3–5 основных разделов. Всегда видна. Лучше всего подходит для разделов одинаковой важности (например, «Главная», «Поиск», «Профиль»).
- Вкладки — для связанного содержимого на одном экране (например, «Все» / «Активные» / «Выполненные»). Часто используются вместе с ViewPager2 для поддержки перелистывания.
Разметка BottomNavigationView
Добавьте BottomNavigationView и FragmentContainerView в разметку Activity:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/navHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:navGraph="@navigation/nav_graph"
app:defaultNavHost="true" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/bottom_nav_menu" />
</LinearLayout>Пункты меню нижней навигации
Определите пункты в res/menu/bottom_nav_menu.xml. ID каждого пункта должен совпадать с ID назначения в графе навигации:
<!-- res/menu/bottom_nav_menu.xml -->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/homeFragment"
android:icon="@drawable/ic_home"
android:title="Home" />
<item
android:id="@+id/searchFragment"
android:icon="@drawable/ic_search"
android:title="Search" />
<item
android:id="@+id/profileFragment"
android:icon="@drawable/ic_person"
android:title="Profile" />
</menu>Подключение к NavController
Свяжите BottomNavigationView с NavController в onCreate():
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navHost = supportFragmentManager
.findFragmentById(R.id.navHostFragment) as NavHostFragment
val navController = navHost.navController
binding.bottomNav.setupWithNavController(navController)
// Hide bottom nav on detail screens:
navController.addOnDestinationChangedListener { _, destination, _ ->
binding.bottomNav.visibility = when (destination.id) {
R.id.detailFragment -> View.GONE
else -> View.VISIBLE
}
}
}
}Значки в нижней навигации
Показывайте значки уведомлений на пунктах нижней навигации:
// Show a numbered badge:
val badge = binding.bottomNav.getOrCreateBadge(R.id.homeFragment)
badge.number = 5
badge.isVisible = true
// Show dot badge (no number):
val dotBadge = binding.bottomNav.getOrCreateBadge(R.id.searchFragment)
dotBadge.isVisible = true
// Remove badge:
binding.bottomNav.removeBadge(R.id.homeFragment)TabLayout
TabLayout отображает горизонтальные вкладки и обычно используется вместе с ViewPager2 для содержимого, которое можно перелистывать:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>ViewPager2 + FragmentStateAdapter
Создайте адаптер, который предоставляет фрагмент для каждой позиции вкладки:
class TasksPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
override fun getItemCount() = 3
override fun createFragment(position: Int): Fragment = when (position) {
0 -> AllTasksFragment()
1 -> ActiveTasksFragment()
2 -> CompletedTasksFragment()
else -> throw IllegalStateException("Unknown tab $position")
}
}TabLayoutMediator
Соедините ViewPager2 и TabLayout с помощью TabLayoutMediator:
// In Fragment.onViewCreated():
val adapter = TasksPagerAdapter(this)
binding.viewPager.adapter = adapter
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
tab.text = when (position) {
0 -> "All"
1 -> "Active"
2 -> "Done"
else -> ""
}
}.attach()
// Disable swipe if needed:
binding.viewPager.isUserInputEnabled = falseВкладки со значками
Добавьте значки на вкладки TabLayout:
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
when (position) {
0 -> {
tab.text = "Home"
tab.setIcon(R.drawable.ic_home)
}
1 -> {
tab.text = "Search"
tab.setIcon(R.drawable.ic_search)
}
2 -> {
tab.text = "Profile"
tab.setIcon(R.drawable.ic_person)
}
}
}.attach()Лимит страниц за пределами экрана
По умолчанию ViewPager2 хранит в памяти только соседнюю страницу. Увеличьте offscreenPageLimit, если вкладки должны оставаться активными при переключении:
// Keep 2 pages on each side alive:
binding.viewPager.offscreenPageLimit = 2
// Note: FragmentStateAdapter saves and restores state for off-screen
// fragments even when offscreenPageLimit is 1 (default).
// Only increase this when you need views (not just state) to survive.Нижняя навигация или вкладки: выбор
Краткое руководство по выбору подходящего шаблона:
- Используйте нижнюю навигацию, если: есть 3–5 разделов верхнего уровня с разным назначением («Главная», «Поиск», «Уведомления», «Профиль»)
- Используйте вкладки, если: нужно фильтровать или распределять по категориям однотипное содержимое (все / активные / архивные задачи)
- Сочетайте оба варианта: нижняя навигация — для разделов верхнего уровня, вкладки внутри раздела — для дополнительной фильтрации
Быстрая проверка
Какой класс соединяет TabLayout с ViewPager2 и задаёт названия вкладок?
Итоги: нижняя навигация и вкладки
Правильная навигация по нескольким разделам:
- BottomNavigationView — 3–5 равнозначных разделов, ID пунктов меню совпадают с ID назначений в графе навигации
setupWithNavController()— автоматическое переключение вкладок и работа с back stack- Значки с помощью
getOrCreateBadge() - TabLayout + ViewPager2 — перелистываемые представления одного и того же содержимого с фильтрацией
TabLayoutMediator— соединяет их и задаёт названия
Далее: модульное тестирование с JUnit для повышения надёжности кода.
Часто задаваемые вопросы
Урок «Нижняя навигация и вкладки» бесплатный?
Да — полный текст урока «Нижняя навигация и вкладки» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Android Academy, подпишись на CoddyKit PRO. Курс Android Academy содержит 5 уроков всего.
Чему я научусь в уроке «Нижняя навигация и вкладки»?
Реализуйте навигацию по разделам с помощью BottomNavigationView, подключённого к NavController, а также вкладки с пролистыванием через TabLayout, ViewPager2 и TabLayoutMediator. Ты практикуешь Android Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Android Academy?
Предыдущий опыт не требуется. Android Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 5 из 5.
Сколько времени занимает урок «Нижняя навигация и вкладки»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Android Academy?
Да. Каждый урок Android Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Основы Material Design
- Темы и стили
- Пользовательские представления
- Анимации и переходы
- Нижняя навигация и вкладки