Áreas Seguras e Entalhes
react-native-safe-area-context e Android edge-to-edge no RN 0.86.
Busque em todas as páginas da documentação
react-native-safe-area-context e Android edge-to-edge no RN 0.86.
Cartão de receita de referência rápida - pronto para copiar e colar.
import { StyleSheet, Text, View } from "react-native";
import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context";
export function AppRoot({ children }: { children: React.ReactNode }) {
return <SafeAreaProvider>{children}</SafeAreaProvider>;
}
export function Screen({ title, children }: { title: string; children: React.ReactNode }) {
return (
<SafeAreaView style={styles.safe} edges={["top", "left", "right"]}>
<View style={styles.header}>
<Text style={styles.title}>{title}</Text>
</View>
<View style={styles.body}>{children}</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
safe: { flex: 1, backgroundColor: "#fff" },
header: { paddingHorizontal: 16, paddingBottom: 8 },
title: { fontSize: 28, fontWeight: "700" },
body: { flex: 1, paddingHorizontal: 16 },
});Quando usar isso: Qualquer layout de tela inteira em iPhones com entalhe, dispositivos com Dynamic Island, ou Android edge-to-edge 15+ onde as barras do sistema se sobrepõem ao seu conteúdo.
import { ScrollView, StatusBar, StyleSheet, Text, View } from "react-native";
import {
SafeAreaProvider,
SafeAreaView,
useSafeAreaInsets,
} from "react-native-safe-area-context";
function ArticleScreen() {
const insets = useSafeAreaInsets();
return (
<View style={styles.screen}>
<StatusBar barStyle="dark-content" translucent backgroundColor="transparent" />
{/* Hero edge-to-edge - inset superior manual para texto legível sob a barra de status */}
<View style={[styles.hero, { paddingTop: insets.top + 12 }]}>
<Text style={styles.heroTitle}>Áreas Seguras</Text>
<Text style={styles.heroSubtitle}>Edge-to-edge com insets legíveis</Text>
</View>
{/* Conteúdo padrão - SafeAreaView cuida dos lados; inset inferior para o indicador de início */}
<SafeAreaView style={styles.content} edges={["left", "right", "bottom"]}>
<ScrollView contentContainerStyle={styles.scroll}>
<Text style={styles.paragraph}>
No RN 0.86, o Android desenha atrás das barras de status e navegação. O iOS faz isso há anos.
react-native-safe-area-context relata o retângulo desobstruído para que sua UI permaneça tocável.
</Text>
</ScrollView>
</SafeAreaView>
</View>
);
}
export default function App() {
return (
<SafeAreaProvider>
<ArticleScreen />
</SafeAreaProvider>
);
}
const styles = StyleSheet.create({
screen: { flex: 1, backgroundColor: "#0f172a" },
hero: {
paddingHorizontal: 20,
paddingBottom: 24,
backgroundColor: "#1e293b",
},
heroTitle: { fontSize: 32, fontWeight: "800", color: "#f8fafc" },
heroSubtitle: { fontSize: 16, color: "#94a3b8", marginTop: 4 },
content: { flex: 1, backgroundColor: "#fff", borderTopLeftRadius: 16, borderTopRightRadius: 16 },
scroll: { padding: 20 },
paragraph: { fontSize: 16, lineHeight: 24, color: "#334155" },
});O que isso demonstra:
SafeAreaProvider na raiz do app para que os valores de inset se propaguem para todas as telas.useSafeAreaInsets() para um hero que se estende de ponta a ponta com padding superior manual.SafeAreaView com edges seletivos - o hero cuida do topo; o conteúdo cuida da parte inferior e dos lados.StatusBar definido como translucent para desenho edge-to-edge do Android atrás da barra de status.react-native-safe-area-context lê os valores nativos de inset e os expõe através do contexto React. É a biblioteca recomendada - incluída em modelos Expo e modelos da comunidade RN.SafeAreaProvider deve envolver seu app (ou cada raiz de modal) para que hooks e SafeAreaView possam ler os insets atuais. O layout raiz do Expo Router normalmente inclui isso.SafeAreaView aplica padding igual ao inset em cada borda selecionada. É um wrapper de conveniência - funcionalmente equivalente a paddingTop: insets.top, etc.useSafeAreaInsets() retorna { top, right, bottom, left } em pixels independentes de densidade. Use-o quando precisar de controle fino (botões flutuantes, cabeçalhos personalizados, padding parcial).edges - um array como ["top", "left", "right"] que omite a parte inferior quando uma barra de abas ou barra de ferramentas do teclado já cuida desse inset.React Native 0.86 (Expo SDK 57) desenha o conteúdo do app atrás das barras de status e navegação do sistema no Android por padrão - alinhando-se com as orientações modernas de edge-to-edge do Android 15+.
| Preocupação | Antes do edge-to-edge | RN 0.86 edge-to-edge |
|---|---|---|
| Sobreposição da barra de status | O sistema reservava uma barra sólida | O conteúdo desenha por trás; adicione inset superior |
| Barra de navegação | Barra de navegação opaca | A barra de gestos/navegação se sobrepõe ao conteúdo; adicione inset inferior |
| Cor de fundo | Definida apenas via StatusBar | Estenda o fundo full-bleed; preencha o conteúdo |
| Teclado | Comportamento padrão | Ainda use KeyboardAvoidingView - separado da área segura |
import { Platform, StatusBar } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
function EdgeToEdgeShell({ children }: { children: React.ReactNode }) {
const insets = useSafeAreaInsets();
return (
<View
style={{
flex: 1,
paddingTop: Platform.OS === "android" ? insets.top : 0, // SafeAreaView geralmente cuida do iOS
paddingBottom: insets.bottom,
}}
>
<StatusBar translucent backgroundColor="transparent" barStyle="dark-content" />
{children}
</View>
);
}Para configuração de edge-to-edge em nível de Gradle e expo-navigation-bar, consulte Edge-to-Edge no Android.
| API | Melhor para | Evitar quando |
|---|---|---|
SafeAreaView | Wrappers de tela inteira, telas simples | Você precisa de padding diferente por sub-região (use o hook) |
useSafeAreaInsets() | Cabeçalhos personalizados, FABs, bottom sheets, mapas | Você copiaria os mesmos quatro paddings em todos os lugares (use SafeAreaView) |
initialWindowMetrics | Transição de splash para app sem flash de inset | Telas normais no app (o provider cuida das atualizações) |
import { useSafeAreaInsets } from "react-native-safe-area-context";
function FloatingActionButton({ onPress }: { onPress: () => void }) {
const insets = useSafeAreaInsets();
return (
<Pressable
onPress={onPress}
style={{
position: "absolute",
right: 16,
bottom: insets.bottom + 16, // limpa o indicador de início / barra de navegação
}}
/>
);
}edges para Cromos Comuns| Tipo de tela | edges recomendado | Por quê |
|---|---|---|
| Tela de pilha (sem abas) | ["top", "left", "right", "bottom"] | Inset completo em todos os lados |
| Conteúdo da tela de abas | ["top", "left", "right"] | A barra de abas cuida do inset inferior |
| Modal / bottom sheet | ["bottom"] ou ["top", "bottom"] | Depende do estilo de apresentação |
| Hero imersivo + corpo | Hook no hero; SafeAreaView no corpo | Propriedade de inset dividida |
import type { EdgeInsets } from "react-native-safe-area-context";
import type { Edge } from "react-native-safe-area-context";
const TAB_EDGES: Edge[] = ["top", "left", "right"];
function useBottomInset(extra = 0): number {
const { bottom } = useSafeAreaInsets();
return bottom + extra;
}
// Passa insets para uma utilidade não-React
function contentHeight(windowHeight: number, insets: EdgeInsets): number {
return windowHeight - insets.top - insets.bottom;
}Edge é "top" | "right" | "bottom" | "left".Usando SafeAreaView principal do react-native - O componente embutido é obsoleto e só lida com entalhes do iOS de forma confiável. Correção: Importe de react-native-safe-area-context.
SafeAreaProvider ausente - useSafeAreaInsets() retorna zeros; o conteúdo fica sob a barra de status. Correção: Envolva a raiz do app (o modelo Expo faz isso; verifique após ejetar ou com uma entrada personalizada).
Padding inferior duplo acima das barras de abas - edges={["bottom"]} em uma tela de abas adiciona padding e a barra de abas adiciona sua própria área segura. Correção: Omita "bottom" de edges quando o navegador de abas for o proprietário desse inset.
Padding superior duplo em SafeAreaViews aninhados - Aninhar dois wrappers ambos com edges={["top"]} dobra o inset. Correção: Um proprietário de área segura por eixo por tela.
Android edge-to-edge sem padding de inset - RN 0.86 desenha atrás das barras do sistema; texto e botões se tornam intocáveis sob a barra de navegação. Correção: Aplique useSafeAreaInsets() ou padding SafeAreaView no conteúdo, não apenas na cor da barra de status.
Ignorando insets de entalhe em paisagem - Insets left e right são diferentes de zero em iPhones com entalhe em paisagem. Correção: Inclua "left" e "right" em edges, ou use o hook para padding horizontal.
Área segura vs. teclado - O inset inferior não se move quando o teclado abre. Correção: Combine a área segura com KeyboardAvoidingView ou react-native-keyboard-controller para campos de texto.
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
react-native-safe-area-context | Padrão para todos os apps de produção | Nunca - esta é a solução padrão |
Hook useSafeAreaInsets | Cabeçalhos personalizados, FABs, mapas, padding parcial | Um wrapper simples de tela inteira é suficiente (SafeAreaView) |
paddingTop: 44 manual | Nunca em produção | Sempre - os valores de inset variam por dispositivo e orientação |
KeyboardAvoidingView | Campos de texto perto da parte inferior da tela | Substituir a área segura - eles resolvem problemas diferentes |
expo-status-bar + expo-navigation-bar | Controlar o estilo/cor da barra em Android edge-to-edge | Medir insets - ainda precisa de safe-area-context |
O SafeAreaView principal só considera as áreas seguras do iOS e está obsoleto. react-native-safe-area-context funciona no iOS e Android, suporta a prop edges e expõe useSafeAreaInsets para controle granular.
Uma vez na raiz do app - tipicamente em App.tsx, _layout.tsx do Expo Router, ou no seu container de navegação. Cada tela e modal que lê insets deve ser um descendente do provider.
Ela lista quais lados recebem padding de inset automático. edges={["top", "left", "right"]} omite a parte inferior - comum em telas de abas onde a barra de abas já limpa o indicador de início. O padrão (omitido) aplica todas as quatro bordas.
O conteúdo agora desenha atrás das barras de status e navegação. Você deve adicionar padding de inset superior e inferior (via SafeAreaView ou useSafeAreaInsets) para que texto e botões permaneçam visíveis e tocáveis. As cores de fundo podem se estender full-bleed atrás das barras.
SafeAreaView - wrapper rápido de tela inteira.useSafeAreaInsets - layouts personalizados (hero edge-to-edge, botão de ação flutuante, overlays de mapa).Eles produzem os mesmos valores de inset; escolha com base na complexidade do layout.
Você provavelmente aplicou edges={["bottom"]} em uma tela dentro de um navegador de abas que já considera o indicador de início. Remova "bottom" de edges em telas raiz de abas.
Envolva o conteúdo do modal com seu próprio SafeAreaProvider apenas se o modal renderizar fora da árvore principal do provider (raro). Geralmente, envolva o conteúdo do modal em SafeAreaView com edges apropriados à apresentação - bottom sheets precisam de inset inferior; modais de tela inteira precisam de todas as bordas.
Sim. Paisagem em iPhones com entalhe move o inset de top para left ou right. useSafeAreaInsets re-renderiza com valores atualizados automaticamente - não armazene insets em cache em useRef entre mudanças de orientação.
Não envolva a imagem em SafeAreaView. Em vez disso, estenda a imagem para top: 0 e adicione paddingTop: insets.top no texto que se sobrepõe à imagem para que os rótulos permaneçam legíveis.
Sim. SafeAreaView é um View com padding. Use style={{ flex: 1 }} como de costume. O padding reduz a área de conteúdo interna - seus filhos flexíveis se organizam dentro da caixa ajustada pelo inset.
import { StatusBar } from "expo-status-bar";
<StatusBar style="auto" translucent />Combine barStyle com seu fundo - texto claro em hero escuro, texto escuro em corpo branco. Veja Edge-to-Edge no Android para temas da barra de navegação.
SafeAreaProvider aceita initialWindowMetrics para popular insets corretos no primeiro frame - reduzindo um salto de layout visível na inicialização fria. Modelos Expo frequentemente configuram isso; adicione se você vir um flash de conteúdo sob a barra de status ao iniciar.
useWindowDimensions retorna o tamanho total da janela. Os insets de área segura descrevem o quanto dessa janela está obstruído. Altura de conteúdo utilizável ≈ height - insets.top - insets.bottom. Veja Dimensões e Layout Responsivo.
Coloque o padding ciente de inset no contentContainerStyle do ScrollView ou envolva a área de rolagem em SafeAreaView. Para um cabeçalho flutuante fora da rolagem, aplique insets.top apenas no cabeçalho.
Não - useSafeAreaInsets().bottom permanece o mesmo quando o teclado abre. Use KeyboardAvoidingView ou uma biblioteca de controle de teclado para mover os campos de entrada acima do teclado separadamente.
flex: 1 dentro de wrappers de área segurabarStyle da barra de status por esquema de coresexpo-navigation-baruseWindowDimensions junto com insetsVersões da Stack: Esta página foi escrita para React 19.2.3, React Native 0.86.0, e Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última atualização: 19 de jul. de 2026