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 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също