Modal Presentation у мобільній розробці: що це, види екранів

Автор: IT Sectr Опубліковано: 2026-06-09 Час читання: 5 хв

Modal Presentation — це спосіб відображення екрана поверх поточного контексту з блокуванням взаємодії з попереднім інтерфейсом. У мобільній розробці модальні вікна використовуються для фокусних завдань: введення даних, підтвердження дій, авторизація та вибір опцій. За даними Apple HIG, 2025, модальні презентації мають займати не більше 20% навігаційних сценаріїв у застосунку. В Android модальність реалізується через DialogFragment, BottomSheet та Activity з певними launch-прапорами.

Головне

  • Modal Presentation — техніка показу екрана, яка блокує взаємодію з попереднім контентом до закриття модального вікна.
  • iOS використовує UIModalPresentationStyle з варіантами .fullScreen, .pageSheet, .formSheet та .automatic.
  • Android реалізує модальність через DialogFragment, BottomSheetDialogFragment та Activity з прапорами Intent.
  • SwiftUI надає модифікатори .sheet та .fullScreenCover для декларативної модальної презентації.
  • Jetpack Compose використовує Dialog та ModalBottomSheet для створення модальних інтерфейсів.

Що таке Modal Presentation?

Modal Presentation — це патерн навігації, за якого новий екран з'являється поверх поточного, тимчасово блокуючи взаємодію з батьківським контентом. Користувач має явно завершити модальне завдання (скасувати, зберегти, закрити), щоб повернутися до попереднього стану.

Модальність вирішує когнітивне завдання: вона фокусує увагу користувача на одній дії без відволікання на решту інтерфейсу. Це критично важливо для форм реєстрації, діалогів підтвердження, вибору файлів та авторизації через сторонні сервіси. Human Interface Guidelines від Apple рекомендують використовувати модальність лише для завдань, які потребують завершення перед продовженням роботи.

На відміну від веб-модальних вікон, мобільна Modal Presentation може бути повноекранною (займає весь екран) або частковою (Page Sheet, Bottom Sheet). Вибір типу залежить від контексту завдання та платформених угод. iOS тяжіє до Page Sheet для більшості сценаріїв, залишаючи Full Screen для відеоплеєрів і фоторедакторів.

Push Presentation (стекова навігація) додає екран у навігаційний стек і автоматично показує кнопку назад. Користувач може повернутися на попередній екран у будь-який момент. Modal Presentation, навпаки, передбачає явне завершення: кнопка назад або відсутня, або закриває модальне вікно, а не повертає на попередній екран.

Основні відмінності між модальною та push-презентацією: Modal Presentation блокує навігацію назад без втрати даних, вимагає дії для закриття (Save, Cancel, Done) і зазвичай представляє окреме завдання. Push Presentation зберігає ієрархію навігації, автоматично додає кнопку повернення та підходить для послідовного перегляду контенту.

ХарактеристикаModal PresentationPush Presentation
Блокування назадТак, потрібна явна діяНі, кнопка назад завжди доступна
Типове використанняФорми, авторизація, вибірДетальний перегляд, навігація
АнімаціяЗнизу вгору (iOS), слайд (Android)Справа наліво (iOS)
Стек навігаціїНе додається в основний стекДодається в стек

На практиці вибір між Modal і Push залежить від контексту. Рекомендується використовувати модальність для завдань, які користувач має завершити перед продовженням, і Push — для послідовного вивчення контенту. Змішування патернів на одному екрані призводить до плутанини та погіршує UX.

Модальна презентація в iOS: UIKit і SwiftUI

iOS пропонує кілька стилів модальної презентації через перелік UIModalPresentationStyle. UIKit підтримує .fullScreen (повний екран), .pageSheet (картка з відступом зверху), .formSheet (центроване вікно на iPad) та .automatic (вибір системою на основі контексту). Починаючи з iOS 13, дефолтним стилем став .automatic, який для iPhone обирає .pageSheet.

UIViewController.present

Базовий метод UIKit для модальної презентації — present(_:animated:completion:). Контролер, який викликає метод, стає presentingViewController, а новий — presentedViewController. Закриття виконується через dismiss(animated:completion:). SwiftUI надає модифікатор .sheet для аналогічної поведінки.

SwiftUI .sheet

Декларативний підхід SwiftUI використовує модифікатори .sheet та .fullScreenCover. Перший створює Page Sheet, другий — повноекранну модальну презентацію. Обидва приймають binding на Bool або об'єкт, що ідентифікується, який керує видимістю модального вікна. Закриття відбувається при встановленні binding у false або виклику dismiss з environment.

swift
struct ContentView: View {
    @State private var showModal = false

    var body: some View {
        Button("Відкрити форму") {
            showModal = true
        }
        .sheet(isPresented: $showModal) {
            RegistrationForm()
        }
    }
}

struct RegistrationForm: View {
    @Environment(\.dismiss) private var dismiss

    var body: some View {
        Button("Зберегти") { dismiss() }
    }
}

Модальна презентація в Android: Fragment і Compose

Android не має єдиного API для модальної презентації, як iOS. Натомість платформа пропонує кілька механізмів: DialogFragment для діалогових вікон, BottomSheetDialogFragment для нижніх панелей та Activity з прапорами NEW_TASK і CLEAR_TOP для модальних екранів. У Jetpack Compose з'явився єдиний компонент Dialog для всіх типів модальних вікон.

DialogFragment

DialogFragment — базовий клас для модальних вікон в Android SDK. Він керує життєвим циклом діалогу, обробляє поворот екрана та зберігає стан. Фрагмент відображається поверх Activity без блокування навігаційного стека. Закриття виконується через dismiss() або натисканням поза областю діалогу, якщо setCancelable(true).

Modal Bottom Sheet

BottomSheetDialogFragment відображає модальне вікно у вигляді панелі, що піднімається знизу. Цей патерн популярний у Material Design для вибору опцій, шерингу та швидких дій. BottomSheet може бути фіксованої висоти або розширюваною (peek height + full height). У Compose використовується ModalBottomSheet із бібліотеки Material3.

kotlin
@Composable
fun ModalScreen(onDismiss: () -> Unit) {
    Dialog(onDismissRequest = onDismiss) {
        Card(
            modifier = Modifier.padding(16.dp)
        ) {
            Column {
                Text("Модальна форма", style = MaterialTheme.typography.headlineSmall)
                Button(onClick = onDismiss) {
                    Text("Закрити")
                }
            }
        }
    }
}

Найкращі практики модальної презентації

Модальні вікна — потужний інструмент UX, але їх надмірне використання погіршує користувацький досвід. Apple HIG і Google Material Design сходяться в рекомендаціях: модальність має застосовуватися для фокусних завдань і не перевищувати 20% від загальної кількості навігаційних дій.

Коли використовувати модальну презентацію

Модальні вікна підходять для сценаріїв: введення даних (форми реєстрації, профілю), підтвердження (видалення, надсилання), вибір (пікер дати, файловий менеджер) та авторизація (OAuth, Firebase Auth). Якщо завдання займає менше 30 секунд і потребує блокування контексту — обирайте модальність.

Чого уникати

Не використовуйте модальну презентацію для: послідовного перегляду контенту (використовуйте Push), відображення помилок (використовуйте Toast або Snackbar), реклами та промо-пропозицій без явного запиту користувача. Material Design рекомендує уникати вкладених модальних вікон — це дезорієнтує користувача та порушує ієрархію навігації.

Для модальних вікон із текстовими полями обов'язково обробляйте втрату фокуса клавіатури. При появі клавіатури модальне вікно має зсуватися вгору, щоб користувач бачив введений текст. UIKeyboardWillShowNotification в iOS та adjustResize в Android вирішують це завдання.

Приклади коду на Swift і Kotlin

Розглянемо реалізацію модальної презентації на обох платформах. Swift приклад показує налаштування UIModalPresentationStyle.pageSheet з делегатом для обробки закриття. Kotlin приклад демонструє DialogFragment із кастомним layout і збереженням стану.

swift
let modalVC = ModalViewController()
modalVC.modalPresentationStyle = .pageSheet

if let sheet = modalVC.sheetPresentationController {
    sheet.detents = [.medium(), .large()]
    sheet.prefersGrabberVisible = true
}

modalVC.presentationController?.delegate = self
present(modalVC, animated: true)

// MARK: - UIAdaptivePresentationControllerDelegate
extension ViewController: UIAdaptivePresentationControllerDelegate {
    func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
        print("Модальне вікно закрито")
    }
}
kotlin
class ModalDialogFragment : DialogFragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_modal, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        view.findViewById<Button>(R.id.closeButton).setOnClickListener {
            dismiss()
        }
    }
}

Часті запитання

Коли слід використовувати Modal Presentation замість Push?

Використовуйте Modal Presentation для фокусних завдань, які користувач має завершити перед продовженням: форми, підтвердження, авторизація. Push підходить для послідовного перегляду контенту, де користувач може вільно повертатися назад. Модальне вікно не повинно містити навігації всередині себе.

Який стиль модальної презентації обрати в iOS?

Починаючи з iOS 13, дефолтний стиль .automatic обирає .pageSheet для iPhone. .pageSheet підходить для більшості сценаріїв (форми, деталі). .fullScreen — для медіаконтенту (відео, фоторедактори). .formSheet — для iPad-застосунків, де потрібне центроване вікно.

Як реалізувати модальне вікно в Jetpack Compose?

Jetpack Compose надає компонент Dialog для простих модальних вікон і ModalBottomSheet для нижніх панелей. Dialog приймає onDismissRequest і контент у Compose-стилі. Для збереження стану використовуйте rememberSaveable всередині діалогу.

Чи можна вкладати модальні вікна одне в одне?

Apple HIG і Material Design не рекомендують вкладені модальні вікна. Якщо користувач відкриває модальне вікно поверх іншого модального вікна, він втрачає контекст і може заплутатися в ієрархії. Замість вкладеності використовуйте Step Indicator або Wizard-патерн з одним модальним вікном.

Як обробити закриття модального вікна при втраті даних?

Використовуйте UIAdaptivePresentationControllerDelegate в iOS (метод presentationControllerShouldDismiss) або OnBackPressedDispatcher в Android. За наявності незбережених даних показуйте AlertDialog з варіантами: зберегти, скасувати зміни, залишитися на екрані. Це запобігає випадковій втраті даних користувачем.

Підсумки

  • Modal Presentation — патерн навігації, що блокує взаємодію з батьківським контентом до завершення завдання.
  • iOS підтримує .fullScreen, .pageSheet, .formSheet через UIModalPresentationStyle і .sheet у SwiftUI.
  • Android реалізує модальність через DialogFragment, BottomSheet і Dialog у Jetpack Compose.
  • Modal відрізняється від Push блокуванням назад і вимогою явної дії для закриття.
  • Модальні вікна не повинні перевищувати 20% навігаційних сценаріїв і не повинні бути вкладеними.
  • Втрату даних при закритті модального вікна потрібно запобігати через делегати та діалоги підтвердження.
  • Рекомендується обирати Page Sheet в iOS і DialogFragment в Android для стандартних модальних завдань.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також