Modal Presentation is a way of displaying a screen on top of the current context, blocking interaction with the previous interface. In mobile development, modal windows are used for focused tasks: data entry, action confirmation, authorization, and option selection. According to Apple HIG, 2025, modal presentations should account for no more than 20% of navigation scenarios in an application. In Android, modality is implemented through DialogFragment, BottomSheet, and Activity with specific launch flags.
Key Takeaways
Modal Presentation is a navigation pattern where a new screen appears on top of the current one, temporarily blocking interaction with the parent content. The user must explicitly complete the modal task (cancel, save, close) to return to the previous state.
Modality solves a cognitive task: it focuses the user’s attention on a single action without distraction from the rest of the interface. This is critically important for registration forms, confirmation dialogs, file selection, and authorization through third-party services. Apple’s Human Interface Guidelines recommend using modality only for tasks that require completion before proceeding.
Unlike web modal windows, mobile Modal Presentation can be full-screen (occupying the entire screen) or partial (Page Sheet, Bottom Sheet). The choice of type depends on the task context and platform conventions. iOS tends toward Page Sheet for most scenarios, leaving Full Screen for video players and photo editors.
Push Presentation (stack navigation) adds a screen to the navigation stack and automatically shows a back button. The user can return to the previous screen at any time. Modal Presentation, on the contrary, requires explicit completion: the back button is either absent or closes the modal window rather than returning to the previous screen.
The main differences between modal and push presentation: Modal Presentation blocks backward navigation without data loss, requires an action to close (Save, Cancel, Done), and usually represents a separate task. Push Presentation preserves the navigation hierarchy, automatically adds a back button, and is suitable for sequential content viewing.
| Characteristic | Modal Presentation | Push Presentation |
|---|---|---|
| Back blocking | Yes, requires explicit action | No, back button always available |
| Typical use | Forms, authorization, selection | Detail view, navigation |
| Animation | Bottom to top (iOS), slide (Android) | Right to left (iOS) |
| Navigation stack | Not added to main stack | Added to stack |
In practice, the choice between Modal and Push depends on the context. It is recommended to use modality for tasks that the user must complete before continuing, and Push for sequential content exploration. Mixing patterns on the same screen leads to confusion and degrades UX.
iOS offers several modal presentation styles through the UIModalPresentationStyle enumeration. UIKit supports .fullScreen (full screen), .pageSheet (card with top inset), .formSheet (centered window on iPad), and .automatic (system chooses based on context). Since iOS 13, the default style has been .automatic, which selects .pageSheet for iPhone.
The basic UIKit method for modal presentation is present(_:animated:completion:). The controller calling the method becomes the presentingViewController, and the new one becomes the presentedViewController. Dismissal is done through dismiss(animated:completion:). SwiftUI provides the .sheet modifier for similar behavior.
The SwiftUI declarative approach uses .sheet and .fullScreenCover modifiers. The first creates a Page Sheet, the second creates a full-screen modal presentation. Both accept a binding to a Bool or an identifiable object that controls the modal window’s visibility. Dismissal occurs when the binding is set to false or when calling dismiss from the environment.
struct ContentView: View {
@State private var showModal = false
var body: some View {
Button("Open Form") {
showModal = true
}
.sheet(isPresented: $showModal) {
RegistrationForm()
}
}
}
struct RegistrationForm: View {
@Environment(\.dismiss) private var dismiss
var body: some View {
Button("Save") { dismiss() }
}
}
Android does not have a single API for modal presentation like iOS. Instead, the platform offers several mechanisms: DialogFragment for dialog windows, BottomSheetDialogFragment for bottom panels, and Activity with NEW_TASK and CLEAR_TOP flags for modal screens. Jetpack Compose introduced a unified Dialog component for all types of modal windows.
DialogFragment is the base class for modal windows in the Android SDK. It manages the dialog’s lifecycle, handles screen rotation, and saves state. The fragment is displayed on top of the Activity without blocking the navigation stack. Dismissal is done through dismiss() or by tapping outside the dialog area if setCancelable(true).
BottomSheetDialogFragment displays a modal window as a panel rising from the bottom. This pattern is popular in Material Design for option selection, sharing, and quick actions. The BottomSheet can be of fixed height or expandable (peek height + full height). In Compose, ModalBottomSheet from the Material3 library is used.
@Composable
fun ModalScreen(onDismiss: () -> Unit) {
Dialog(onDismissRequest = onDismiss) {
Card(
modifier = Modifier.padding(16.dp)
) {
Column {
Text("Modal Form", style = MaterialTheme.typography.headlineSmall)
Button(onClick = onDismiss) {
Text("Close")
}
}
}
}
}
Modal windows are a powerful UX tool, but their excessive use degrades the user experience. Apple HIG and Google Material Design agree on recommendations: modality should be used for focused tasks and should not exceed 20% of all navigation actions.
Modal windows are suitable for scenarios: data entry (registration forms, profiles), confirmation (deletion, submission), selection (date picker, file manager), and authorization (OAuth, Firebase Auth). If the task takes less than 30 seconds and requires context blocking — choose modality.
Do not use modal presentation for: sequential content viewing (use Push), error display (use Toast or Snackbar), advertisements and promotional offers without explicit user request. Material Design recommends avoiding nested modal windows — this disorients the user and disrupts the navigation hierarchy.
For modal windows with text fields, be sure to handle keyboard focus loss. When the keyboard appears, the modal window should shift upward so the user can see the text being entered. UIKeyboardWillShowNotification in iOS and adjustResize in Android solve this task.
Let’s look at implementing modal presentation on both platforms. The Swift example shows configuring UIModalPresentationStyle.pageSheet with a delegate for handling dismissal. The Kotlin example demonstrates DialogFragment with a custom layout and state preservation.
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("Modal dismissed")
}
}
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()
}
}
}
Frequently Asked Questions
Use Modal Presentation for focused tasks that the user must complete before continuing: forms, confirmations, authorization. Push is suitable for sequential content viewing where the user can freely navigate back. A modal window should not contain navigation within itself.
Since iOS 13, the default .automatic style selects .pageSheet for iPhone. .pageSheet is suitable for most scenarios (forms, details). .fullScreen is for media content (video, photo editors). .formSheet is for iPad apps that need a centered window.
Jetpack Compose provides the Dialog component for simple modal windows and ModalBottomSheet for bottom panels. Dialog accepts onDismissRequest and content in Compose style. Use rememberSaveable inside the dialog for state preservation.
Apple HIG and Material Design do not recommend nested modal windows. If a user opens a modal window on top of another modal window, they lose context and may become confused about the hierarchy. Instead of nesting, use a Step Indicator or Wizard pattern with a single modal window.
Use UIAdaptivePresentationControllerDelegate in iOS (presentationControllerShouldDismiss method) or OnBackPressedDispatcher in Android. When there are unsaved changes, show an AlertDialog with options: save, discard changes, or stay on screen. This prevents accidental data loss by the user.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also