Sheet é um componente de interface que aparece na parte inferior da tela sobre o conteúdo principal e fornece ações ou informações adicionais. Bottom Sheet é o tipo mais comum, definido nas diretrizes do Material Design 3 (Google, 2024). Ao contrário das janelas de diálogo, um Sheet não bloqueia completamente a interação com o fundo e suporta os estados collapsed e expanded. Compreender os tipos e o comportamento do Sheet é necessário para construir uma navegação conveniente em aplicativos móveis.
Pontos principais
Sheet é um componente de interface de nível superficial que desliza de baixo da tela e exibe conteúdo ou ações adicionais sem tirar o usuário da tela atual. Ao contrário das transições de tela cheia, um Sheet preserva o contexto: o usuário vê a tela de fundo e entende de onde o Sheet apareceu.
A arquitetura de um Sheet é baseada em um contêiner de altura ajustável. No seu estado mínimo (collapsed), apenas parte do conteúdo é visível — normalmente um título ou um pequeno painel. O usuário pode arrastar o Sheet para cima para expandi-lo (expanded) ou deslizá-lo para baixo para fechá-lo. Este comportamento lembra uma folha de papel física sendo puxada de debaixo de uma pilha — daí o nome.
O Google nas diretrizes do Material Design 3 (2024) destaca dois cenários principais para usar Sheet: exibir ações adicionais que não cabem na barra de ferramentas principal e mostrar formulários ou informações detalhadas sem navegar para uma tela separada. No iOS, a Apple adicionou suporte nativo a Sheet a partir do iOS 15 através do UISheetPresentationController, confirmando a universalidade do padrão.
Material Design define três tipos de Bottom Sheet, cada um com seu próprio comportamento e área de aplicação. Escolher o tipo correto afeta diretamente a experiência do usuário e a conformidade com as diretrizes da plataforma.
Bottom Sheet padrão é um componente não modal: o usuário pode interagir com a tela de fundo sem fechar o Sheet. Por exemplo, enquanto navega por uma lista de produtos em segundo plano, o usuário vê filtros em um Bottom Sheet e pode alterá-los sem fechar o painel. O Sheet ajusta sua altura ao conteúdo — de 30% a 90% da tela.
O Bottom Sheet padrão não bloqueia o fundo e permite a interação com o conteúdo principal. Esta é uma diferença chave em relação ao Sheet modal, que requer uma ação obrigatória para continuar. Use um Sheet padrão quando a informação adicional não for crítica para o cenário principal.
Bottom Sheet modal bloqueia a interação com a tela de fundo até que o usuário realize uma ação dentro do Sheet. Esse Sheet é sempre mostrado no estado expandido e requer um fechamento explícito — através de um botão, ação ou deslize para baixo. O Material Design recomenda o Sheet modal para formulários de login, confirmações e configurações críticas.
No Android, o Bottom Sheet modal é implementado através do BottomSheetDialogFragment, que bloqueia automaticamente o fundo. No iOS, um comportamento similar é fornecido pela variante modal do UISheetPresentationController com o parâmetro .mediumDetent. O Sheet modal só deve ser usado quando o contexto requer a atenção do usuário.
Bottom Sheet expandido combina as propriedades do padrão e do modal: começa como não modal no estado collapsed, mas ao ser arrastado para cima torna-se modal. Na prática, isso significa que o usuário pode primeiro dar uma olhada no conteúdo e depois decidir — expandir o Sheet para estudo detalhado ou fechá-lo.
Este padrão é especialmente popular em mapas e navegadores, onde o painel inferior mostra informações breves sobre um ponto de rota e, ao deslizar para cima, expande-se com detalhes. O Google Maps usa exatamente este Sheet expandido para exibir informações sobre lugares e rotas.
| Tipo de Sheet | Bloqueio de fundo | Estado inicial | Exemplo |
|---|---|---|---|
| Padrão | Não | Collapsed | Filtros no catálogo |
| Modal | Sim | Expanded | Formulário de login |
| Expandido | Parcial | Collapsed | Cartão de lugar |
Android SDK fornece várias APIs para implementar Bottom Sheet, desde a abordagem clássica baseada em View até o moderno Jetpack Compose. A biblioteca Material Components para Android inclui implementações prontas de BottomSheetDialogFragment e BottomSheetBehavior.
BottomSheetBehavior é uma classe do Material Components que se anexa a qualquer View e controla sua posição na tela. O desenvolvedor define três estados: STATE_COLLAPSED, STATE_EXPANDED e STATE_HIDDEN. O Behavior lida automaticamente com gestos de arrasto e animação.
val sheet = findViewById<View>(R.id.bottom_sheet)
val behavior = BottomSheetBehavior.from(sheet)
behavior.state = BottomSheetBehavior.STATE_COLLAPSED
behavior.peekHeight = 200
Jetpack Compose fornece uma API mais declarativa através do componente ModalBottomSheet do Material 3. Ao contrário da abordagem baseada em View, no Compose o Bottom Sheet é uma função composable que aceita estado e conteúdo. O Sheet anima automaticamente a aparição, ocultação e mudanças de altura ao arrastar.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FilterSheet(onDismiss: () -> Unit) {
ModalBottomSheet(onDismissRequest = onDismiss) {
Text("Filtros")
Button(onClick = onDismiss) { Text("Aplicar") }
}
}
BottomSheetDialogFragment é um DialogFragment especializado que é exibido como Bottom Sheet. Ele lida automaticamente com modalidade, ciclo de vida e mudanças de configuração. O desenvolvedor só precisa sobrescrever onCreateView e retornar o layout do Sheet. De acordo com a documentação do Google (Android Developers, 2024), BottomSheetDialogFragment é a abordagem recomendada para Bottom Sheets modais no Android clássico.
Apple introduziu suporte nativo a Sheet a partir do iOS 15 através do UISheetPresentationController. Antes disso, os desenvolvedores implementavam Bottom Sheet manualmente com transições personalizadas ou bibliotecas de terceiros. O Sheet nativo da Apple suporta detents — níveis de expansão predefinidos.
UISheetPresentationController é um controlador de apresentação embutido que exibe um View Controller como Sheet. O desenvolvedor especifica um array de detents — valores de altura nos quais o Sheet pode parar. O iOS 16 adicionou detents personalizados com altura arbitrária. A Apple recomenda usar os detents medium (.medium) e large (.large) como principais.
let viewController = MySheetViewController()
if let sheet = viewController.sheetPresentationController {
sheet.detents = [.medium, .large]
sheet.prefersGrabberVisible = true
sheet.preferredCornerRadius = 16
}
present(viewController, animated: true)
SwiftUI fornece o modificador .sheet, que vincula a exibição do Sheet a um estado. Quando uma variável publicada se torna true, o SwiftUI mostra automaticamente o Sheet. O SwiftUI também suporta detents através do modificador .presentationDetents, adicionado no iOS 16.
struct ContentView: View {
@State private var showSheet = false
var body: some View {
Button("Mostrar Sheet") { showSheet = true }
.sheet(isPresented: $showSheet) {
FilterView()
.presentationDetents([.medium, .large])
}
}
}
Frameworks multiplataforma também suportam Bottom Sheet, adaptando o comportamento à plataforma alvo. Flutter e React Native fornecem implementações embutidas e personalizadas com diferentes graus de flexibilidade.
Flutter SDK contém dois métodos para exibir Bottom Sheet: showBottomSheet (padrão) e showModalBottomSheet (modal). O Material Design no Flutter segue os mesmos princípios que no Android — o Sheet aparece de baixo, suporta arrasto e tem altura ajustável. Para comportamento expandido com detents, usa-se DraggableScrollableSheet.
Scaffold.of(context).showBottomSheet((context) {
return Container(
padding: EdgeInsets.all(16),
child: Column(
children: [
Text("Conteúdo do Sheet"),
ElevatedButton(
onPressed: () => Navigator.of(context).pop(),
child: Text("Fechar")
)
]
)
);
})
React Native não tem um componente Bottom Sheet embutido em seu núcleo, então os desenvolvedores usam bibliotecas de terceiros. A mais popular é @gorhom/bottom-sheet (mais de 7 mil estrelas no GitHub, 2024). Ela fornece um Bottom Sheet orientado a gestos com suporte para snap points, animações e cabeçalhos fixos. A biblioteca é construída sobre Reanimated 2 e Gesture Handler para desempenho a 60 FPS.
O uso correto do Bottom Sheet requer o cumprimento das diretrizes da plataforma e a compreensão dos cenários em que um Sheet é adequado. Vamos revisar as principais recomendações e erros comuns ao projetar Sheets.
Bottom Sheet é ótimo para ações que são complementares ao conteúdo principal da tela. Filtros, ordenação, seleção de opções, informações breves sobre um item — cenários típicos. O Material Design recomenda usar Bottom Sheet para ferramentas que não devem ocupar a tela inteira, mas requerem mais espaço que um Action Sheet ou Popup Menu.
Não use Bottom Sheet para avisos críticos ou erros — para isso, as janelas de diálogo são mais adequadas. Evite Sheets com grande número de campos de entrada que exigem rolagem: o usuário tem dificuldade para alcançar o teclado e perde contexto. Se um Sheet contiver mais de sete itens de ação, considere uma tela separada em vez de um Sheet.
Um erro típico é definir peekHeight (altura no estado recolhido) para mais de 40% da tela. O usuário não sabe se está vendo o Sheet inteiro ou se pode ser expandido. O Material Design recomenda peekHeight entre 15-30% da altura da tela para deixar uma parte notável do conteúdo oculta e motivar o arrasto.
No iOS, os usuários esperam que um Sheet possa ser fechado deslizando para baixo de qualquer posição. Se você desabilitar este gesto (através de UISheetPresentationController.prefersEdgeAttachedInCompactHeight), o usuário fica frustrado ao tentar fechar o Sheet da maneira habitual. As Diretrizes de Interface Humana da Apple (2024) enfatizam que deslizar para fechar é uma expectativa básica do usuário iOS.
Perguntas frequentes
Bottom Sheet não bloqueia completamente o fundo e suporta arrasto, enquanto uma janela de diálogo é modal e requer uma ação obrigatória. Bottom Sheet é mais adequado para opções complementares, o diálogo para confirmações críticas.
Sim, mas é necessário configurar adjustResize ou adjustPan no manifesto do Android. No iOS, o teclado levanta automaticamente o Sheet. Flutter e React Native requerem manipulação manual através do MediaQuery para posicionamento correto.
Recomenda-se não mais de 5-7 itens em um Sheet padrão. Se houver mais conteúdo, use rolagem ou divisão em categorias. O Material Design aconselha não exceder 90% da altura da tela no estado expandido.
Para um Sheet modal, defina setCancelable(true) no Android ou isModalInPresentation = false no iOS. No Jetpack Compose, onDismissRequest lida automaticamente com o toque no fundo. No SwiftUI, deslizar para baixo é o comportamento padrão.
Sim, todas as implementações nativas suportam VoiceOver e TalkBack. Certifique-se de que o FocusManager mova corretamente o foco para o Sheet ao abri-lo e o retorne ao fechá-lo. Implementações personalizadas requerem configuração manual de acessibilidade.
Resumo
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.
Leia também