Capítulo 05: Material Design 3, Temas Dinâmicos (Monet), Tipografia e Shapes

Especialização em Mobile Nativo com Android • Kotlin 2.0 & Jetpack Compose


🗺️ Mapa Conceitual do Design System Material 3 (M3)

flowchart TD
    SOURCE["Origem Cromática (Wallpaper do Usuário ou Paleta de Marca)"] --> MONET["Algoritmo de Extração de Paleta Dinâmica (Monet)"]
    
    subgraph TOKENS["Geração Automática de Tokens de Cor M3"]
        MONET --> PRIMARY["Primary / OnPrimary / PrimaryContainer"]
        MONET --> SECONDARY["Secondary / OnSecondary / SecondaryContainer"]
        MONET --> TERTIARY["Tertiary / OnTertiary (Harmonização Externa)"]
        MONET --> SURFACE["Surface / OnSurface / SurfaceVariant"]
        MONET --> ERROR["Error / OnError / ErrorContainer"]
    end

    subgraph THEME["Provedor de Tema Compose (MaterialTheme)"]
        PRIMARY --> COLOR_SCHEME["ColorScheme (lightColorScheme / darkColorScheme)"]
        SURFACE --> COLOR_SCHEME
        TYPO["Typography (Display, Headline, Title, Body, Label)"]
        SHAPES["Shapes (ExtraSmall, Small, Medium, Large, ExtraLarge)"]
        COLOR_SCHEME --> M3_THEME["MaterialTheme { ... }"]
        TYPO --> M3_THEME
        SHAPES --> M3_THEME
    end

    M3_THEME -->|"Injetado via CompositionLocal"| UI_COMPONENTS["Scaffold / Card / Button / NavigationBar"]

    style SOURCE fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px
    style MONET fill:#b3e5fc,stroke:#0288d1,stroke-width:2px
    style COLOR_SCHEME fill:#fff3e0,stroke:#ff9800,stroke-width:2px
    style M3_THEME fill:#ede7f6,stroke:#7e57c2,stroke-width:2px
    style UI_COMPONENTS fill:#e8f5e9,stroke:#4caf50,stroke-width:2px

🏛️ 1. O Design System Material You e a Arquitetura M3

O Material Design 3 (M3), também conhecido como Material You, representa uma revolução de personalização e acessibilidade no ecossistema Android. Diferente do Material 2, que impunha paletas estáticas e rígidas, o M3 introduz o conceito de co-criação com o usuário:

  1. Dynamic Color (Monet Engine): A partir do Android 12 (API 31), o sistema operacional analisa as cores predominantes do papel de parede do usuário e gera dinamicamente 5 paletas tonais com 13 tons cromáticos calculados. O Jetpack Compose acessa esse motor nativo através das funções dynamicLightColorScheme(context) e dynamicDarkColorScheme(context).
  2. Sistema Tonal de Contraste e Acessibilidade: No M3, as relações de cores são construídas com pares canônicos como primary e onPrimary ou surfaceContainer e onSurface. Isso assegura que o contraste mínimo exigido pelas diretrizes WCAG (Web Content Accessibility Guidelines) seja matematicamente garantido em qualquer combinação dinâmica.
  3. Escala Tipográfica Hierárquica: A tipografia M3 é estruturada em 15 papéis tipográficos semânticos divididos em 5 categorias principais: Display, Headline, Title, Body e Label — cada um com variantes Large, Medium e Small.

📊 2. Comparativo Arquitetural: Material 2 vs Material 3 (Compose)

Dimensão Visual & Técnica Material Design 2 (M2) Material Design 3 (M3 / Material You) Benefício de Adoção
Cores Dinâmicas Inexistente (Cores estáticas de marca no tema) Suporte nativo a dynamicColorScheme via Monet Engine O app se integra harmonicamente ao gosto visual do usuário
Pares de Contraste Apenas primary, primaryVariant e background Pares ricos: Container, OnContainer, Inverse, Outlines Garantia matemática de legibilidade e acessibilidade
Contornos & Cantos (Shapes) Cantos retangulares ou com raio pequeno padrão Curvaturas mais expressivas e pílulas completas (shape = CircleShape) Aparência moderna, tátil e amigável ao toque
Elevação Visual Controlada por sombras artificiais pesadas (elevation = 8.dp) Controlada principalmente por preenchimento de cor tonal (surfaceContainerHigh) Economia de GPU e melhor visualização em telas OLED
Componentes Nativos BottomNavigation, TopAppBar genéricos NavigationBar, CenterAlignedTopAppBar, LargeTopAppBar Suporte imediato a scroll behaviors e comportamentos colapsáveis

💻 3. Laboratório Prático: Tema Completo com Suporte Dinâmico e Modos Claro/Escuro

O código abaixo define a estrutura oficial recomendada para criar o tema do aplicativo no Jetpack Compose com suporte ao Dynamic Color e fallback seguro para versões anteriores ao Android 12:

package br.com.portal.mobile.android.cap05

import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Shapes
import androidx.compose.material3.Typography
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp

// 1. Paletas Estáticas de Fallback (para Android < 12 ou preferências de marca)
private val DarkCustomColorScheme = darkColorScheme(
    primary = Color(0xFFA5C8FF),
    onPrimary = Color(0xFF00315F),
    primaryContainer = Color(0xFF004785),
    onPrimaryContainer = Color(0xFFD4E3FF),
    surface = Color(0xFF1A1C1E),
    onSurface = Color(0xFFE2E2E6)
)

private val LightCustomColorScheme = lightColorScheme(
    primary = Color(0xFF005EB4),
    onPrimary = Color(0xFFFFFFFF),
    primaryContainer = Color(0xFFD4E3FF),
    onPrimaryContainer = Color(0xFF001C3B),
    surface = Color(0xFFFDFBFF),
    onSurface = Color(0xFF1A1C1E)
)

// 2. Escala Tipográfica Padronizada
val AppTypography = Typography(
    titleLarge = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Bold,
        fontSize = 22.sp,
        lineHeight = 28.sp
    ),
    bodyMedium = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Normal,
        fontSize = 14.sp,
        lineHeight = 20.sp
    )
)

// 3. Função de Tema Global da Aplicação
@Composable
fun PortalAndroidTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    dynamicColor: Boolean = true, // Ativa cores do wallpaper em Android 12+
    content: @Composable () -> Unit
) {
    val context = LocalContext.current

    val colorScheme = when {
        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
            if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
        }
        darkTheme -> DarkCustomColorScheme
        else -> LightCustomColorScheme
    }

    MaterialTheme(
        colorScheme = colorScheme,
        typography = AppTypography,
        content = content
    )
}

⚠️ 4. Armadilhas Comuns no Uso do Material 3

  1. Cores Hardcoded em Componentes: Escrever modifier.background(Color.White) ou Text(color = Color.Black) quebra totalmente o suporte ao Dark Mode. Utilize invariavelmente MaterialTheme.colorScheme.surface e MaterialTheme.colorScheme.onSurface.
  2. Misturar Bibliotecas M2 e M3: Certifique-se de importar sempre classes do pacote androidx.compose.material3.*. Importar artefatos do androidx.compose.material.* (M2) causa conflitos de temas e inconsistências de renderização visual.
  3. Ignorar Cores Dinâmicas em Telas de Branding: Se sua aplicação possui uma identidade corporativa estrita (por exemplo, um banco que exige estritamente tom vermelho ou laranja), configure dynamicColor = false para impedir que o papel de parede do usuário altere a identidade visual da empresa.