Apresentação Modal no desenvolvimento móvel: o que é, tipos de telas

Autor: IT Sectr Publicado: 2026-06-09 Tempo de leitura: 5 min

Apresentação Modal é uma forma de exibir uma tela sobre o contexto atual, bloqueando a interação com a interface anterior. No desenvolvimento móvel, janelas modais são usadas para tarefas focadas: entrada de dados, confirmação de ações, autorização e seleção de opções. De acordo com Apple HIG, 2025, apresentações modais não devem ocupar mais de 20% dos cenários de navegação em um aplicativo. No Android, a modalidade é implementada através de DialogFragment, BottomSheet e Activity com flags de inicialização específicos.

Pontos principais

  • Apresentação Modal é uma técnica de exibição de tela que bloqueia a interação com o conteúdo anterior até que a janela modal seja fechada.
  • iOS usa UIModalPresentationStyle com as variantes .fullScreen, .pageSheet, .formSheet e .automatic.
  • Android implementa modalidade através de DialogFragment, BottomSheetDialogFragment e Activity com flags Intent.
  • SwiftUI fornece os modificadores .sheet e .fullScreenCover para apresentação modal declarativa.
  • Jetpack Compose usa Dialog e ModalBottomSheet para criar interfaces modais.

O que é Apresentação Modal?

Apresentação Modal é um padrão de navegação onde uma nova tela aparece sobre a atual, bloqueando temporariamente a interação com o conteúdo pai. O usuário deve completar explicitamente a tarefa modal (cancelar, salvar, fechar) para retornar ao estado anterior.

A modalidade resolve uma tarefa cognitiva: ela foca a atenção do usuário em uma única ação sem distração do resto da interface. Isso é criticamente importante para formulários de registro, diálogos de confirmação, seleção de arquivos e autorização através de serviços de terceiros. As Human Interface Guidelines da Apple recomendam usar modalidade apenas para tarefas que exigem conclusão antes de prosseguir.

Ao contrário das janelas modais web, a Apresentação Modal móvel pode ser em tela cheia (ocupando toda a tela) ou parcial (Page Sheet, Bottom Sheet). A escolha do tipo depende do contexto da tarefa e das convenções da plataforma. iOS tende a usar Page Sheet para a maioria dos cenários, deixando Full Screen para players de vídeo e editores de foto.

Push Presentation (navegação por pilha) adiciona uma tela à pilha de navegação e mostra automaticamente um botão de voltar. O usuário pode retornar à tela anterior a qualquer momento. Apresentação Modal, ao contrário, exige conclusão explícita: o botão de voltar está ausente ou fecha a janela modal em vez de retornar à tela anterior.

As principais diferenças entre apresentação modal e push: Apresentação Modal bloqueia a navegação para trás sem perda de dados, requer uma ação para fechar (Save, Cancel, Done) e geralmente representa uma tarefa separada. Push Presentation preserva a hierarquia de navegação, adiciona automaticamente um botão de voltar e é adequado para visualização sequencial de conteúdo.

CaracterísticaApresentação ModalPush Presentation
Bloqueio de retornoSim, requer ação explícitaNão, botão de voltar sempre disponível
Uso típicoFormulários, autorização, seleçãoVisualização detalhada, navegação
AnimaçãoDe baixo para cima (iOS), deslizar (Android)Da direita para a esquerda (iOS)
Pilha de navegaçãoNão adicionada à pilha principalAdicionada à pilha

Na prática, a escolha entre Modal e Push depende do contexto. É recomendado usar modalidade para tarefas que o usuário deve completar antes de continuar, e Push para exploração sequencial de conteúdo. Misturar padrões na mesma tela causa confusão e degrada a UX.

Apresentação Modal no iOS: UIKit e SwiftUI

iOS oferece vários estilos de apresentação modal através da enumeração UIModalPresentationStyle. UIKit suporta .fullScreen (tela cheia), .pageSheet (cartão com margem superior), .formSheet (janela centralizada no iPad) e .automatic (sistema escolhe baseado no contexto). Desde o iOS 13, o estilo padrão é .automatic, que seleciona .pageSheet para iPhone.

UIViewController.present

O método básico do UIKit para apresentação modal é present(_:animated:completion:). O controlador que chama o método se torna presentingViewController, e o novo se torna presentedViewController. O fechamento é feito através de dismiss(animated:completion:). SwiftUI fornece o modificador .sheet para comportamento similar.

SwiftUI .sheet

A abordagem declarativa do SwiftUI usa os modificadores .sheet e .fullScreenCover. O primeiro cria um Page Sheet, o segundo cria uma apresentação modal em tela cheia. Ambos aceitam um binding a um Bool ou objeto identificável que controla a visibilidade da janela modal. O fechamento ocorre quando o binding é definido como false ou ao chamar dismiss do ambiente.

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

    var body: some View {
        Button("Abrir formulário") {
            showModal = true
        }
        .sheet(isPresented: $showModal) {
            RegistrationForm()
        }
    }
}

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

    var body: some View {
        Button("Salvar") { dismiss() }
    }
}

Apresentação Modal no Android: Fragment e Compose

Android não tem uma única API para apresentação modal como o iOS. Em vez disso, a plataforma oferece vários mecanismos: DialogFragment para janelas de diálogo, BottomSheetDialogFragment para painéis inferiores e Activity com flags NEW_TASK e CLEAR_TOP para telas modais. Jetpack Compose introduziu um componente Dialog unificado para todos os tipos de janelas modais.

DialogFragment

DialogFragment é a classe base para janelas modais no Android SDK. Ela gerencia o ciclo de vida do diálogo, lida com a rotação da tela e salva o estado. O fragmento é exibido sobre a Activity sem bloquear a pilha de navegação. O fechamento é feito através de dismiss() ou tocando fora da área do diálogo se setCancelable(true).

Modal Bottom Sheet

BottomSheetDialogFragment exibe uma janela modal como um painel que se eleva da parte inferior. Este padrão é popular no Material Design para seleção de opções, compartilhamento e ações rápidas. O BottomSheet pode ter altura fixa ou expansível (altura de visualização + altura total). No Compose, ModalBottomSheet da biblioteca Material3 é usado.

kotlin
@Composable
fun ModalScreen(onDismiss: () -> Unit) {
    Dialog(onDismissRequest = onDismiss) {
        Card(
            modifier = Modifier.padding(16.dp)
        ) {
            Column {
                Text("Formulário modal", style = MaterialTheme.typography.headlineSmall)
                Button(onClick = onDismiss) {
                    Text("Fechar")
                }
            }
        }
    }
}

Melhores práticas de apresentação modal

Janelas modais são uma ferramenta poderosa de UX, mas seu uso excessivo degrada a experiência do usuário. Apple HIG e Google Material Design concordam nas recomendações: a modalidade deve ser usada para tarefas focadas e não deve exceder 20% do total de ações de navegação.

Quando usar apresentação modal

Janelas modais são adequadas para cenários: entrada de dados (formulários de registro, perfis), confirmação (exclusão, envio), seleção (seletor de data, gerenciador de arquivos) e autorização (OAuth, Firebase Auth). Se a tarefa leva menos de 30 segundos e requer bloqueio de contexto, escolha modalidade.

O que evitar

Não use apresentação modal para: visualização sequencial de conteúdo (use Push), exibição de erros (use Toast ou Snackbar), anúncios e ofertas promocionais sem solicitação explícita do usuário. Material Design recomenda evitar janelas modais aninhadas, pois isso desorienta o usuário e interrompe a hierarquia de navegação.

Para janelas modais com campos de texto, certifique-se de lidar com a perda de foco do teclado. Quando o teclado aparece, a janela modal deve se deslocar para cima para que o usuário veja o texto sendo digitado. UIKeyboardWillShowNotification no iOS e adjustResize no Android resolvem essa tarefa.

Exemplos de código em Swift e Kotlin

Vamos ver a implementação da apresentação modal em ambas as plataformas. O exemplo em Swift mostra a configuração de UIModalPresentationStyle.pageSheet com um delegado para lidar com o fechamento. O exemplo em Kotlin demonstra DialogFragment com um layout personalizado e preservação de estado.

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("Modal fechado")
    }
}
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()
        }
    }
}

Perguntas frequentes

Quando devo usar Apresentação Modal em vez de Push?

Use Apresentação Modal para tarefas focadas que o usuário deve completar antes de continuar: formulários, confirmações, autorização. Push é adequado para visualização sequencial de conteúdo onde o usuário pode navegar livremente para trás. Uma janela modal não deve conter navegação dentro de si.

Qual estilo de apresentação modal escolher no iOS?

Desde o iOS 13, o estilo padrão .automatic seleciona .pageSheet para iPhone. .pageSheet é adequado para a maioria dos cenários (formulários, detalhes). .fullScreen é para conteúdo de mídia (vídeo, editores de foto). .formSheet é para aplicativos iPad que precisam de uma janela centralizada.

Como implementar uma janela modal no Jetpack Compose?

Jetpack Compose fornece o componente Dialog para janelas modais simples e ModalBottomSheet para painéis inferiores. Dialog aceita onDismissRequest e conteúdo no estilo Compose. Use rememberSaveable dentro do diálogo para preservação de estado.

Janelas modais podem ser aninhadas umas dentro das outras?

Apple HIG e Material Design não recomendam janelas modais aninhadas. Se um usuário abre uma janela modal sobre outra janela modal, ele perde o contexto e pode ficar confuso sobre a hierarquia. Em vez de aninhar, use um Indicador de Etapa ou padrão de Assistente com uma única janela modal.

Como lidar com o fechamento de janela modal com perda de dados?

Use UIAdaptivePresentationControllerDelegate no iOS (método presentationControllerShouldDismiss) ou OnBackPressedDispatcher no Android. Quando houver alterações não salvas, mostre um AlertDialog com opções: salvar, descartar alterações ou permanecer na tela. Isso evita a perda acidental de dados pelo usuário.

Resumo

  • Apresentação Modal é um padrão de navegação que bloqueia a interação com o conteúdo pai até que a tarefa seja concluída.
  • iOS suporta .fullScreen, .pageSheet, .formSheet via UIModalPresentationStyle e .sheet no SwiftUI.
  • Android implementa modalidade através de DialogFragment, BottomSheet e Dialog no Jetpack Compose.
  • Modal difere do Push por bloquear a navegação para trás e exigir uma ação explícita para fechar.
  • Janelas modais não devem exceder 20% dos cenários de navegação e não devem ser aninhadas.
  • Perda de dados ao fechar uma janela modal deve ser prevenida através de delegados e diálogos de confirmação.
  • É recomendado escolher Page Sheet no iOS e DialogFragment no Android para tarefas modais padrão.

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também