💻 Exemplos: Capítulo 05: Material Design 3, Temas e Dynamic Color
Exemplos de Código: Capítulo 05 — Material Design 3 e Temas Dinâmicos
Especialização em Mobile Nativo com Android • Demonstrações Práticas Compiláveis
💻 Código de Demonstração: Configuração de Tema M3, Dynamic Color e Tipografia Customizada
O código abaixo demonstra a criação de um Design System completo para Android com Material Design 3:
- Suporte a Dynamic Color (Android 12+ / API 31+) que extrai a paleta de cores do papel de parede do usuário.
- Definição de paletas estáticas de contingência para Modo Claro e Modo Escuro.
- Customização de Tipografia e aplicação consistente em componentes corporativos.
package br.com.portal.mobile.android.cap05
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ColorScheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
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.Modifier
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.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
// =====================================================================
// 1. Definição de Cores Estáticas (Brand Colors)
// =====================================================================
private val AzulPrimarioLight = Color(0xFF0061A4)
private val AzulSecundarioLight = Color(0xFF535F70)
private val FundoLight = Color(0xFFFDFBFF)
private val AzulPrimarioDark = Color(0xFF9ECAFF)
private val AzulSecundarioDark = Color(0xFFBBC7DB)
private val FundoDark = Color(0xFF1A1C1E)
private val LightColorScheme = lightColorScheme(
primary = AzulPrimarioLight,
secondary = AzulSecundarioLight,
background = FundoLight,
surface = FundoLight,
onPrimary = Color.White
)
private val DarkColorScheme = darkColorScheme(
primary = AzulPrimarioDark,
secondary = AzulSecundarioDark,
background = FundoDark,
surface = FundoDark,
onPrimary = Color(0xFF003258)
)
// =====================================================================
// 2. Customização Tipográfica
// =====================================================================
val PortalTypography = Typography(
headlineMedium = TextStyle(
fontFamily = FontFamily.SansSerif,
fontWeight = FontWeight.Bold,
fontSize = 24.sp,
lineHeight = 32.sp
),
bodyLarge = TextStyle(
fontFamily = FontFamily.SansSerif,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp
),
labelLarge = TextStyle(
fontFamily = FontFamily.SansSerif,
fontWeight = FontWeight.Medium,
fontSize = 14.sp
)
)
// =====================================================================
// 3. Tema M3 Dinâmico da Aplicação
// =====================================================================
@Composable
fun PortalTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colorScheme: ColorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
MaterialTheme(
colorScheme = colorScheme,
typography = PortalTypography,
shapes = MaterialTheme.shapes.copy(medium = RoundedCornerShape(16.dp)),
content = content
)
}
// =====================================================================
// 4. Demonstração de Componentes sob o Tema
// =====================================================================
@Composable
fun DesignSystemShowcase() {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(24.dp)
) {
Text(
text = "Material 3 Design System",
style = MaterialTheme.typography.headlineMedium,
color = MaterialTheme.colorScheme.primary
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "Cores adaptativas com Material You e Dynamic Color ativado.",
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Spacer(modifier = Modifier.height(24.dp))
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "Card com Cor Surface Variant",
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "O contraste de cores atende rigorosamente as diretrizes WCAG AAA de acessibilidade visual.",
style = MaterialTheme.typography.bodyMedium
)
}
}
Spacer(modifier = Modifier.height(24.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
Button(onClick = {}, modifier = Modifier.weight(1f)) {
Text("Primário")
}
OutlinedButton(onClick = {}, modifier = Modifier.weight(1f)) {
Text("Contorno")
}
}
}
}
}
@Preview(name = "M3 Claro", showBackground = true)
@Composable
fun M3LightPreview() {
PortalTheme(darkTheme = false, dynamicColor = false) {
DesignSystemShowcase()
}
}
@Preview(name = "M3 Escuro", showBackground = true)
@Composable
fun M3DarkPreview() {
PortalTheme(darkTheme = true, dynamicColor = false) {
DesignSystemShowcase()
}
}