Как организовать экраны и перелистывание в Android
Короткий ответ: Navigation — для маршрутов и back‑stack, ViewPager2 — для локального перелистывания страниц; чаще всего лучшая схема — NavHost на уровне Activity и ViewPager2 внутри отдельных фрагментов, а состояние хранить в ViewModel.
Когда нужен ViewPager2, а когда Navigation
- Navigation (Jetpack) нужен, если нужен прозрачный стек экранов, deep links, Safe Args и корректная обработка Back.
- ViewPager2 подходит, когда пользователь ожидает свайп: онбординг, галереи, карточки, горизонтальные ленты.
- Если "pager" — это последовательность шагов с ветвлением логики (условные переходы, пропуски), лучше реализовать каждый шаг как отдельный фрагмент в навграфе.
Типичная ошибка — строить сложный многошаговый поток (регистрация, checkout) целиком на ViewPager2: потом сложно поддерживать возвраты, ветвления и состояние.
Практические схемы сочетания и примеры
- ViewPager2 внутри одного фрагмента (onboarding, слайды)
- Навигатор знает только OnboardingFragment как один экран.
- Внутри него ViewPager2 показывает слайды (фрагменты или View).
- Обработка системной кнопки Back делается локально: если currentItem > 0 — листаем назад, иначе вызываем стандартный onBackPressed.
Пример обработки Back (кратко):
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
if (viewPager.currentItem > 0) viewPager.currentItem -= 1
else { isEnabled = false; requireActivity().onBackPressedDispatcher.onBackPressed() }
}
- Навигация на верхнем уровне + ViewPager2 внутри таба
- Одна Activity с NavHostFragment.
- Навграф описывает верхние разделы (Home, Profile...). Внутри HomeFragment может быть ViewPager2 для локального перелистывания контента.
- Такой подход сохраняет понятный стек и позволяет иметь отдельные состояния для каждого таба.
- Полный отказ от ViewPager2, если нужен back‑stack на каждый шаг
- Создавайте отдельные фрагменты в nav_graph и используйте кастомные анимации slide_in/slide_out, чтобы имитировать свайп.
- Это даёт корректный back‑stack и поддержку deep links.
Храните логику и состояние в ViewModel, а не во фрагментах ViewPager2 — это существенно упрощает сохранение состояния и тестирование.
Настройки и подводные камни ViewPager2
- isUserInputEnabled — включить/отключить свайп.
- offscreenPageLimit — сколько страниц держать в памяти (баланс памать/плавность).
- Не помещайте в pager очень тяжёлые фрагменты с картами и множ. списками — лучше навигация + отдельные фрагменты.
Частые ошибки
- Пытаться реализовать всю навигацию приложения внутри ViewPager2.
- Игнорировать системный Back для pager‑страниц.
- Дублировать логику навигации в разных местах вместо вынесения в NavGraph.
- Хранить состояние только в фрагментах — при пересоздании теряются данные.
FAQ
- Нужно ли использовать несколько Activity? Обычно достаточно одной Activity + NavHost.
- Можно ли вложить NavHost внутри ViewPager2? Да, но избегайте сложных nested NavHost без явной нужды — это усложняет жизненный цикл и навигацию.
- Как сделать переход от онбординга в основной граф? Навигируйте из OnboardingFragment в целевой фрагмент через findNavController().navigate(action).
Следуйте простой формуле: Navigation управляет маршрутизацией и стеком, ViewPager2 — отображением соседних страниц внутри экрана. Совмещайте их тогда, когда задача чётко разделяется на «маршруты» и «локальное перелистывание».