Episode ini membangun konsistensi visual lewat MaterialTheme: color scheme, typography, dan shapes, dukungan light dan dark theme, dynamic color di Android 12, serta tokenisasi design system untuk aplikasi berskala.

Aplikasi yang rapi tidak lahir dari warna yang dipilih sembarangan. Di balik setiap layar yang enak dilihat ada sistem: kumpulan warna, tipografi, dan bentuk yang konsisten. Di Compose, sistem itu disebut MaterialTheme.
Semua komponen Material 3 yang kalian pakai di episode 4 membaca theme: tombol, teks, dan card otomatis mengambil warna dan bentuk dari theme. Ubah satu token, seluruh aplikasi ikut berubah. Inilah kekuatan theming yang terpusat.
Episode 6 ini meliputi struktur MaterialTheme, dukungan light dan dark, dynamic color, dan design system tokenization.
Setiap aplikasi Compose punya file Theme.kt yang mendefinisikan ColorScheme. Warna tidak disimpan sebagai warna lepas, melainkan sebagai peran: primary, secondary, surface, background, dan seterusnya. Komponen mengambil peran ini, bukan warna langsung.
private val LightColors = lightColorScheme(
primary = Color(0xFF3B5BDB),
secondary = Color(0xFF5E81AC),
surface = Color(0xFFFAFAFA),
onPrimary = Color.White
)lightColorScheme mengisi peran warna untuk mode terang. Dengan memakai peran, perubahan branding cukup dilakukan di satu tempat — seluruh tombol dan surface ikut menyesuaikan.
Typography mendefinisikan gaya teks mulai dari displayLarge sampai labelSmall, sedangkan Shapes mengontrol sudut komponen:
val AppTypography = Typography(
headlineMedium = TextStyle(
fontWeight = FontWeight.Bold,
fontSize = 28.sp,
lineHeight = 36.sp
)
)
val AppShapes = Shapes(
small = RoundedCornerShape(8.dp),
medium = RoundedCornerShape(12.dp),
large = RoundedCornerShape(16.dp)
)Text memakai gaya bawaan seperti headlineMedium lewat MaterialTheme.typography, sehingga hierarki tipografi konsisten di seluruh layar.
Semua token diikat dalam satu composable theme:
@Composable
fun BelajarComposeTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val colorScheme = if (darkTheme) DarkColors else LightColors
MaterialTheme(
colorScheme = colorScheme,
typography = AppTypography,
shapes = AppShapes,
content = content
)
}MaterialTheme menyediakan warna, tipografi, dan bentuk ke seluruh subtree. isSystemInDarkTheme() membaca pengaturan sistem — dasar dukungan mode gelap. Untuk melihat hasil theme di perangkat, bangun dan pasang aplikasi dengan ./gradlew :app:installDebug.
Mode gelap bukan sekadar warna terbalik. Peran seperti surface dan onSurface perlu diatur ulang agar kontras tetap terjaga di latar gelap. Definisikan DarkColors sebagai pasangan dari LightColors:
private val DarkColors = darkColorScheme(
primary = Color(0xFF8FA8FF),
secondary = Color(0xFF9BB4E8),
surface = Color(0xFF121212),
onPrimary = Color(0xFF1A1A2E)
)darkColorScheme mengisi peran untuk mode gelap. Dengan pola di atas, aplikasi otomatis berganti theme saat sistem berpindah mode — tanpa logika tambahan di setiap screen.
Kadang pengguna ingin mengunci theme, misalnya selalu gelap. Simpan preferensi itu di DataStore (episode 11) dan teruskan nilai darkTheme secara eksplisit ke BelajarComposeTheme sebagai parameter.
Di Android 12 ke atas, dynamic color mengambil warna dari wallpaper pengguna dan menerapkannya ke aplikasi. dynamicDarkColorScheme dan dynamicLightColorScheme menyediakan skema itu secara otomatis:
val context = LocalContext.current
val colorScheme = if (dynamicColor && Build.VERSION.SDK_INT >= 31) {
if (darkTheme) dynamicDarkColorScheme(context)
else dynamicLightColorScheme(context)
} else {
if (darkTheme) DarkColors else LightColors
}dynamicDarkColorScheme(context) menghasilkan skema dari wallpaper. Untuk perangkat di bawah Android 12, kalian jatuh kembali ke skema statis. Fitur ini memberikan rasa personalisasi yang kuat dengan sedikit kode.
Saat tim tumbuh, token harus dibakukan. Kumpulkan semua nilai dalam satu object yang bisa dipakai di mana saja:
object Spacing {
val xs = 4.dp
val sm = 8.dp
val md = 16.dp
val lg = 24.dp
}
object Dimensi {
val radiusCard = 16.dp
val tinggiTopBar = 64.dp
}Token seperti Spacing.md menggantikan angka ajaib di seluruh codebase. Perubahan desain cukup dilakukan di object ini — konsistensi dan kecepatan iterasi naik bersama-sama.
Episode 6 membangun sistem visual: MaterialTheme dengan ColorScheme, Typography, dan Shapes, dukungan light dan dark theme lewat isSystemInDarkTheme, dynamic color di Android 12 dengan dynamicLightColorScheme, serta tokenisasi design system untuk aplikasi berskala.
Inti yang harus dibawa pulang:
isSystemInDarkTheme menghubungkan theme dengan mode sistem.Di episode 7 selanjutnya kita akan membahas handling input dan events — TextField, Button, Checkbox, dan Switch, deteksi gesture, fokus dan keyboard, validasi input, serta Snackbar, dialog, dan bottom sheet.