Views, Text & Core Components
Layout primitives, text nesting rules, and platform-specific rendering quirks.
Busque em todas as páginas da documentação
Layout primitives, text nesting rules, and platform-specific rendering quirks.
Cartão de receita de referência rápida - pronto para copiar e colar.
import { StyleSheet, Text, View, ScrollView, SafeAreaView } from "react-native";
export function ProfileCard({ name, bio }: { name: string; bio: string }) {
return (
<SafeAreaView style={styles.safe}>
<ScrollView contentContainerStyle={styles.scroll}>
<View style={styles.card}>
<Text style={styles.title}>{name}</Text>
<Text style={styles.body}>
{bio}
{"\n"}
<Text style={styles.link}>Read more</Text>
</Text>
</View>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
safe: { flex: 1, backgroundColor: "#f5f5f5" },
scroll: { padding: 16 },
card: {
backgroundColor: "#fff",
borderRadius: 12,
padding: 16,
gap: 8,
},
title: { fontSize: 20, fontWeight: "600" },
body: { fontSize: 16, lineHeight: 24, color: "#333" },
link: { color: "#2563eb", fontWeight: "500" },
});Quando usar isto: Você está construindo qualquer layout de tela - cartões, listas, cabeçalhos - e precisa dos primitivos View/Text fundamentais com rolagem segura e insets conscientes de notch.
import { useState } from "react";
import {
Platform,
Pressable,
ScrollView,
StyleSheet,
Text,
View,
} from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
type Tab = "posts" | "about";
interface Post {
id: string;
title: string;
excerpt: string;
}
const POSTS: Post[] = [
{ id: "1", title: "Hermes on device", excerpt: "Startup wins from a compact bytecode runtime." },
{ id: "2", title: "Fabric layout", excerpt: "Shadow nodes commit straight to the native tree." },
];
export default function FeedScreen() {
const [tab, setTab] = useState<Tab>("posts");
return (
<SafeAreaView style={styles.safe} edges={["top", "left", "right"]}>
<View style={styles.header}>
<Text style={styles.heading}>RN Fundamentals</Text>
<View style={styles.tabs}>
{(["posts", "about"] as const).map((key) => (
<Pressable
key={key}
onPress={() => setTab(key)}
style={[styles.tab, tab === key && styles.tabActive]}
>
<Text style={[styles.tabLabel, tab === key && styles.tabLabelActive]}>
{key === "posts" ? "Posts" : "About"}
</Text>
</Pressable>
))}
</View>
</View>
<ScrollView
contentContainerStyle={styles.content}
keyboardShouldPersistTaps="handled"
>
{tab === "posts" ? (
POSTS.map((post) => (
<View key={post.id} style={styles.card}>
<Text style={styles.cardTitle}>{post.title}</Text>
<Text style={styles.cardBody} numberOfLines={2}>
{post.excerpt}
</Text>
</View>
))
) : (
<Text style={styles.cardBody}>
Built with Expo SDK 57, React Native 0.86, and React 19.2.3.
</Text>
)}
</ScrollView>
<View
style={[
styles.footer,
Platform.select({ ios: styles.footerIos, android: styles.footerAndroid }),
]}
>
<Text style={styles.footerText}>© 2026 Mobile Cookbook</Text>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
safe: { flex: 1, backgroundColor: "#f8fafc" },
header: { paddingHorizontal: 16, paddingBottom: 8, gap: 12 },
heading: { fontSize: 28, fontWeight: "700", color: "#0f172a" },
tabs: { flexDirection: "row", gap: 8 },
tab: {
paddingHorizontal: 14,
paddingVertical: 8,
borderRadius: 999,
backgroundColor: "#e2e8f0",
},
tabActive: { backgroundColor: "#2563eb" },
tabLabel: { fontSize: 14, fontWeight: "600", color: "#334155" },
tabLabelActive: { color: "#fff" },
content: { padding: 16, gap: 12, paddingBottom: 32 },
card: {
backgroundColor: "#fff",
borderRadius: 12,
padding: 16,
gap: 6,
...Platform.select({
ios: {
shadowColor: "#000",
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.08,
shadowRadius: 8,
},
android: { elevation: 3 },
}),
},
cardTitle: { fontSize: 17, fontWeight: "600", color: "#0f172a" },
cardBody: { fontSize: 15, lineHeight: 22, color: "#475569" },
footer: {
paddingHorizontal: 16,
paddingVertical: 12,
borderTopWidth: StyleSheet.hairlineWidth,
borderTopColor: "#cbd5e1",
},
footerIos: { paddingBottom: 4 },
footerAndroid: { paddingBottom: 8 },
footerText: { fontSize: 12, color: "#64748b", textAlign: "center" },
});O que isso demonstra:
View como contêiner de layout com flexbox (gap, flexDirection) e sombra/elevação específicas da plataforma.Text para spans com estilo inline dentro de um parágrafo.ScrollView com contentContainerStyle para preenchimento de conteúdo rolável.SafeAreaView de react-native-safe-area-context com edges explícitos.Platform.select para pequenas diferenças de estilo iOS/Android em um arquivo.numberOfLines para truncamento de texto em nós de texto nativos.View se torna UIView no iOS e android.view.ViewGroup no Android.flexDirection padrão é column, oposta aos padrões típicos da web.Text é mapeado para UILabel / TextView. Strings são renderizadas pelo motor de texto nativo, não como HTML.StyleSheet.create registra os estilos uma vez; em tempo de desenvolvimento, ele valida os nomes das propriedades contra o esquema de estilo do RN.| Componente | Papel | Uso Típico |
|---|---|---|
View | Caixa de layout | Linhas, cartões, wrappers, alvos de toque |
Text | Renderização de texto | Rótulos, parágrafos, spans inline |
ScrollView | Rolagem delimitada | Formulários curtos, configurações, páginas de detalhes |
FlatList | Rolagem virtualizada | Listas longas (veja a seção de desempenho) |
Image | Bitmaps e ícones | Avatares, imagens principais (require ou URI) |
TextInput | Texto editável | Formulários, barras de pesquisa |
Pressable | Feedback de toque | Botões, linhas de lista (veja o artigo de tratamento de eventos) |
SafeAreaView | Shell ciente de insets | Telas sob notches e indicadores de início |
| Regra | iOS | Android |
|---|---|---|
Strings brutas devem estar dentro de <Text> | Exigido (redbox) | Exigido (redbox) |
<Text> aninhado herda estilos do pai | Sim | Sim |
numberOfLines trunca com reticências | Sim | Sim |
onPress em Text aninhado | Suportado | Suportado |
| Semântica HTML de nível de bloco | N/A - sem <p>, <div> | N/A |
// Válido - link inline dentro da cópia do corpo
<Text style={styles.body}>
Tap here to {" "}
<Text style={styles.link} onPress={openDocs}>
open the docs
</Text>
.
</Text>
// Inválido - string diretamente sob View
<View>
Hello {/* redbox: Text strings must be rendered within a <Text> component */}
</View>// Padrões flex do RN (diferente do navegador)
// flexDirection: 'column'
// alignItems: 'stretch'
// flexShrink: 0 em filhos (web frequentemente encolhe)
// position: 'relative' apenas - 'fixed'/'sticky' precisam de bibliotecas
<View style={{ flex: 1 }}> {/* preenche o pai no eixo principal */}
<View style={{ flex: 1 }} /> {/* divide o espaço restante com irmãos */}
</View>import type { StyleProp, TextStyle, ViewStyle } from "react-native";
interface CardProps {
title: string;
children: React.ReactNode;
style?: StyleProp<ViewStyle>;
titleStyle?: StyleProp<TextStyle>;
}
// StyleProp<T> aceita um único estilo, array ou entradas falsas
const merged: StyleProp<ViewStyle> = [styles.card, isActive && styles.cardActive, style];React de react; os tipos de props do componente ficam ao lado do componente.StyleProp<ViewStyle> / StyleProp<TextStyle> para substituições de estilo opcionais.const styles = StyleSheet.create({...}) para que as chaves sejam verificadas exaustivamente.react-native-safe-area-context e digite edges como Edge[].Strings fora de Text - Colocar "Hello" diretamente dentro de View gera um redbox de desenvolvimento. Correção: Envolva todas as strings visíveis pelo usuário em <Text>.
Assumindo layout de linha - Copiar trechos flex da web com direção de linha implícita empilha os filhos verticalmente. Correção: Defina flexDirection: "row" explicitamente quando quiser layout horizontal.
Padding em ScrollView vs conteúdo - Colocar padding no próprio ScrollView recorta os indicadores de rolagem de forma estranha no iOS. Correção: Use contentContainerStyle para preenchimento interno.
Sombra no Android - As props shadowColor / shadowOffset do iOS são ignoradas no Android. Correção: Emparelhe as props de sombra do iOS com elevation via Platform.select.
Duplo padding de área segura - Aninhar SafeAreaView dentro de outro wrapper seguro adiciona um inset superior excessivo. Correção: Aplique a área segura uma vez na raiz da tela; use edges para controlar quais lados recebem inset.
numberOfLines sem restrição de largura - O truncamento pode não aparecer se o nó de texto se expandir livremente. Correção: Restrinja a largura com flex: 1, width, ou flexShrink pai.
Árvores View profundas para estilo de texto - Envolver cada palavra em View quebra o fluxo inline e prejudica a acessibilidade. Correção: Aninhe Text dentro de Text para spans inline.
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
Primitivos View + Text | Controle total, aprendendo os fundamentos, sistemas de design personalizados | Você precisa de um kit de componentes completo pronto para uso |
@rneui/themed / React Native Paper | Componentes temáticos ou Material consistentes enviam mais rápido | O tamanho do bundle ou a luta de substituição de estilo importam |
Layouts Stack do expo-router | Chrome de navegação, cabeçalhos e shells de tela | Você só precisa de um layout de cartão estático |
FlatList em vez de ScrollView | 50+ linhas homogêneas, virtualização necessária | Telas de conteúdo misto curtas (formulários, dashboards) |
CSS via react-native-unistyles / Tamagui | Tematização baseada em tokens entre plataformas | Uma única tela com um punhado de regras StyleSheet |
UILabel / TextView.View é apenas um contêiner de layout; ele não pode renderizar glifos.column - os filhos se empilham verticalmente de cima para baixo.flexDirection: "row" explicitamente para barras de ferramentas horizontais e linhas de chips.<Text style={styles.body}>
Already have an account?{" "}
<Text style={styles.link} onPress={goToLogin}>
Sign in
</Text>
</Text>Text aninhado herda o tamanho da fonte e a cor do pai, a menos que substituído.ScrollView renderiza todos os filhos de uma vez - bom para conteúdo curto.FlatList virtualiza linhas - necessário para feeds longos para evitar custo de memória e layout.ScrollView é mais simples e previsível.shadowColor, shadowOffset, shadowOpacity, shadowRadius.elevation no fundo da view.Platform.select dentro de StyleSheet.create.style aplica-se à viewport de rolagem (a janela visível).contentContainerStyle aplica-se ao wrapper interno que se move ao rolar.gap e flexGrow: 1 em contentContainerStyle, não em style.SafeAreaView de react-native-safe-area-context (incluído nos modelos Expo).edges={["top", "left", "right"]} para evitar padding inferior duplo acima das barras de abas.Text aceita onPress, onLongPress e pressRetentionOffset.Pressable com um filho Text para papéis mais claros e alvos de toque maiores.Text.gap, rowGap e columnGap são suportados no React Native 0.71+.View e ScrollView contentContainerStyle.numberOfLines precisa de uma largura limitada para medir o overflow.flex: 1, uma width fixa ou flexShrink: 1 no Text ou na linha pai.StyleSheet.create valida chaves, permite reutilização e é mais limpo em diffs.{ opacity: pressed ? 0.6 : 1 }).style={[styles.base, { backgroundColor: color }]}.Text nesting, formas de estilo) permanecem inalteradas da perspectiva do desenvolvedor.<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Centered</Text>
</View>justifyContent alinha no eixo principal (coluna = vertical).alignItems alinha no eixo cruzado (coluna = horizontal).width: "100%" e height: "50%" resolvem contra o pai.useWindowDimensions no artigo de dimensões.pointerEvents="none" permite que os toques passem para as views abaixo - útil para overlays decorativos.box-none ignora toques no contêiner, mas permite que os filhos os recebam.auto; altere apenas ao depurar alvos de toque sobrepostos.Pressable, gestos e hitSlopuseWindowDimensionsImage, buckets de densidade e carregamento de assets.ios / .androidVersõ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