1. Giriş
Bu codelab'de, Materyal Tasarım 3'ü kullanarak Jetpack Compose'da uygulamalarınıza tema uygulama hakkında bilgi edineceksiniz. Ayrıca, uygulamanızı kişiselleştirilmiş ve erişilebilir şekilde temalandırmanıza yardımcı olan Materyal Tasarım 3'ün temel yapı taşları (renk şemaları, tipografi ve şekiller) hakkında da bilgi edineceksiniz.
Ayrıca, farklı vurgu düzeyleriyle birlikte dinamik temalandırma desteğini de keşfedeceksiniz.
Öğrenecekleriniz
Bu codelab'de şunları öğreneceksiniz:
- Material 3 temalandırmanın temel özellikleri
- Material 3 renk şemaları ve uygulamanız için tema oluşturma
- Uygulamanızda dinamik ve açık/koyu tema desteği
- Uygulamanızı kişiselleştirmek için kullanılan tipografi ve şekiller
- Materyal 3 bileşenleri ve uygulamanızı şekillendirmek için özelleştirme
Ne oluşturacaksınız?
Bu codelab'de, Reply adlı bir e-posta istemcisi uygulamasını temalandıracaksınız. Temel temayı kullanarak stil içermeyen bir uygulamayla başlarsınız. Öğrendiklerinizi uygulamayı temalandırmak ve koyu temaları desteklemek için kullanırsınız.

Temel tema ile uygulamamızın varsayılan başlangıç noktası.
Renk şeması, tipografi ve şekillerle temanızı oluşturup uygulamanızın e-posta listesine ve ayrıntılar sayfasına uygularsınız. Ayrıca uygulamaya dinamik tema desteği de ekleyeceksiniz. Bu codelab'in sonunda, uygulamanızda hem renk hem de dinamik tema desteği olacak.

Açık renk teması ve açık dinamik tema içeren tema geliştirme laboratuvarının son noktası.

Koyu renk teması ve koyu dinamik tema içeren temalandırma codelab'inin son noktası.
İhtiyacınız olanlar
- Android Studio'nun en son sürümü
- Kotlin dili ile ilgili temel deneyim
- Jetpack Compose hakkında temel bilgiler
- Row, Column ve Modifier gibi Compose düzenleri hakkında temel bilgi
2. Hazırlanma
Bu adımda, bu codelab'de stilini belirleyeceğiniz Yanıtla uygulamasının tam kodunu indirirsiniz.
Kodu alın
Bu codelab'in kodunu android-compose-codelabs GitHub deposunda bulabilirsiniz. Klonlamak için şu komutu çalıştırın:
$ git clone https://github.com/googlecodelabs/android-compose-codelabs
Alternatif olarak iki ZIP dosyası indirebilirsiniz:
Örnek uygulamaya göz atma
Yeni indirdiğiniz kod, mevcut tüm Compose codelab'lerinin kodunu içerir. Bu codelab'i tamamlamak için Android Studio'da ThemingCodelab projesini açın.
Ana daldaki kodla başlamanızı ve codelab'i kendi hızınızda adım adım uygulamanızı öneririz. Projenin git dalını değiştirerek Android Studio'da istediğiniz zaman her iki sürümü de çalıştırabilirsiniz.
Başlangıç kodunu keşfetme
Ana kod, etkileşimde bulunacağınız aşağıdaki ana paketleri ve dosyaları içeren bir kullanıcı arayüzü paketi içerir:
MainActivity.kt: Reply uygulamasını başlattığınız giriş noktası etkinliği.com.example.reply.ui.theme: Bu pakette temalar, tipografi ve renk şemaları bulunur. Bu pakete Material teması ekleyeceksiniz.com.example.reply.ui.components– Liste Öğeleri, Uygulama Çubukları gibi uygulamanın özel bileşenlerini içerir. Temaları bu bileşenlere uygularsınız.ReplyApp.kt: Bu, kullanıcı arayüzü ağacının başlayacağı ana Composable işlevimizdir. Bu dosyada üst düzey temalandırma uygulayacaksınız.
Bu codelab'de ui paket dosyalarına odaklanılacaktır.
3. Material 3 Teması Oluşturma
Jetpack Compose, dijital arayüzler oluşturmak için kapsamlı bir tasarım sistemi olan Materyal Tasarım'ın bir uygulamasını sunar. Materyal Tasarım bileşenleri (düğmeler, kartlar, anahtarlar vb.), Materyal Tasarım'ı ürününüzün markasını daha iyi yansıtacak şekilde özelleştirmenin sistematik bir yolu olan Materyal Teması Oluşturma üzerine kurulmuştur.
Materyal 3 teması, uygulamanıza tema eklemek için aşağıdaki alt sistemlerden oluşur: renk şeması, tipografi ve şekiller. Bu değerleri özelleştirdiğinizde değişiklikleriniz, uygulamanızı oluşturmak için kullandığınız M3 bileşenlerine otomatik olarak yansıtılır. Şimdi her bir alt sisteme ayrıntılı olarak bakalım ve bunları örnek uygulamada uygulayalım.

Renkler, tipografi ve şekillerden oluşan Material 3 alt sistemi.
4. Renk şemaları
Renk şemasının temelini, her biri Material 3 bileşenleri tarafından kullanılan 13 tonluk bir ton paletiyle ilişkili olan beş temel renk oluşturur.

M3 teması oluşturmak için beş temel anahtar renk.
Her vurgu rengi (birincil, ikincil ve üçüncül) daha sonra eşleştirme, vurgu tanımlama ve görsel ifade için farklı tonlarda dört uyumlu renkte sağlanır.

Birincil, ikincil ve üçüncül temel vurgu renklerinin dört tonu.
Benzer şekilde, nötr renkler de yüzeyler ve arka plan için kullanılan dört uyumlu tona ayrılır. Bunlar, herhangi bir yüzeye yerleştirildiğinde metin simgelerini vurgulamak için de önemlidir.

Temel nötr renklerin dört tonlu rengi.
Renk şeması ve renk rolleri hakkında daha fazla bilgi edinin.
Renk şemaları oluşturma
Özel bir ColorScheme manuel olarak oluşturabilirsiniz ancak genellikle markanızın kaynak renklerini kullanarak oluşturmak daha kolaydır. Material Theme Builder aracı bunu yapmanıza ve isteğe bağlı olarak Compose temalandırma kodunu dışa aktarmanıza olanak tanır.
İstediğiniz rengi seçebilirsiniz ancak kullanım alanımız için varsayılan Yanıt birincil rengini #825500 kullanacaksınız. Soldaki Temel renkler bölümünde Birincil rengi tıklayın ve renk seçiciye kodu ekleyin.

Materyal Tema Oluşturucu'ya birincil renk kodu ekleme.
Material Theme Builder'a birincil rengi ekledikten sonra aşağıdaki temayı ve sağ üst köşede dışa aktarma seçeneğini görürsünüz. Bu codelab'de temayı Jetpack Compose'da dışa aktarırsınız.

Sağ üst köşede dışa aktarma seçeneğinin bulunduğu Material Theme Builder
Birincil renk #825500, uygulamaya ekleyeceğiniz aşağıdaki temayı oluşturur. Material 3, bir bileşenin durumunu, belirginliğini ve vurgusunu esnek bir şekilde ifade etmek için çok çeşitli renk rolleri sunar.

Ana renkten açık ve koyu renk şeması dışa aktarıldı.
The Color.kt Oluşturulan dosya, hem açık hem de koyu tema renkleri için tanımlanan tüm rollerle birlikte temanızın renklerini içerir.
Color.kt
package com.example.reply.ui.theme
import androidx.compose.ui.graphics.Color
val md_theme_light_primary = Color(0xFF825500)
val md_theme_light_onPrimary = Color(0xFFFFFFFF)
val md_theme_light_primaryContainer = Color(0xFFFFDDB3)
val md_theme_light_onPrimaryContainer = Color(0xFF291800)
val md_theme_light_secondary = Color(0xFF6F5B40)
val md_theme_light_onSecondary = Color(0xFFFFFFFF)
val md_theme_light_secondaryContainer = Color(0xFFFBDEBC)
val md_theme_light_onSecondaryContainer = Color(0xFF271904)
val md_theme_light_tertiary = Color(0xFF51643F)
val md_theme_light_onTertiary = Color(0xFFFFFFFF)
val md_theme_light_tertiaryContainer = Color(0xFFD4EABB)
val md_theme_light_onTertiaryContainer = Color(0xFF102004)
val md_theme_light_error = Color(0xFFBA1A1A)
val md_theme_light_errorContainer = Color(0xFFFFDAD6)
val md_theme_light_onError = Color(0xFFFFFFFF)
val md_theme_light_onErrorContainer = Color(0xFF410002)
val md_theme_light_background = Color(0xFFFFFBFF)
val md_theme_light_onBackground = Color(0xFF1F1B16)
val md_theme_light_surface = Color(0xFFFFFBFF)
val md_theme_light_onSurface = Color(0xFF1F1B16)
val md_theme_light_surfaceVariant = Color(0xFFF0E0CF)
val md_theme_light_onSurfaceVariant = Color(0xFF4F4539)
val md_theme_light_outline = Color(0xFF817567)
val md_theme_light_inverseOnSurface = Color(0xFFF9EFE7)
val md_theme_light_inverseSurface = Color(0xFF34302A)
val md_theme_light_inversePrimary = Color(0xFFFFB951)
val md_theme_light_shadow = Color(0xFF000000)
val md_theme_light_surfaceTint = Color(0xFF825500)
val md_theme_light_outlineVariant = Color(0xFFD3C4B4)
val md_theme_light_scrim = Color(0xFF000000)
val md_theme_dark_primary = Color(0xFFFFB951)
val md_theme_dark_onPrimary = Color(0xFF452B00)
val md_theme_dark_primaryContainer = Color(0xFF633F00)
val md_theme_dark_onPrimaryContainer = Color(0xFFFFDDB3)
val md_theme_dark_secondary = Color(0xFFDDC2A1)
val md_theme_dark_onSecondary = Color(0xFF3E2D16)
val md_theme_dark_secondaryContainer = Color(0xFF56442A)
val md_theme_dark_onSecondaryContainer = Color(0xFFFBDEBC)
val md_theme_dark_tertiary = Color(0xFFB8CEA1)
val md_theme_dark_onTertiary = Color(0xFF243515)
val md_theme_dark_tertiaryContainer = Color(0xFF3A4C2A)
val md_theme_dark_onTertiaryContainer = Color(0xFFD4EABB)
val md_theme_dark_error = Color(0xFFFFB4AB)
val md_theme_dark_errorContainer = Color(0xFF93000A)
val md_theme_dark_onError = Color(0xFF690005)
val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6)
val md_theme_dark_background = Color(0xFF1F1B16)
val md_theme_dark_onBackground = Color(0xFFEAE1D9)
val md_theme_dark_surface = Color(0xFF1F1B16)
val md_theme_dark_onSurface = Color(0xFFEAE1D9)
val md_theme_dark_surfaceVariant = Color(0xFF4F4539)
val md_theme_dark_onSurfaceVariant = Color(0xFFD3C4B4)
val md_theme_dark_outline = Color(0xFF9C8F80)
val md_theme_dark_inverseOnSurface = Color(0xFF1F1B16)
val md_theme_dark_inverseSurface = Color(0xFFEAE1D9)
val md_theme_dark_inversePrimary = Color(0xFF825500)
val md_theme_dark_shadow = Color(0xFF000000)
val md_theme_dark_surfaceTint = Color(0xFFFFB951)
val md_theme_dark_outlineVariant = Color(0xFF4F4539)
val md_theme_dark_scrim = Color(0xFF000000)
val seed = Color(0xFF825500)
The Theme.kt Oluşturulan dosya, açık ve koyu renk şemaları ile uygulama teması için bir kurulum içerir. Ayrıca, ana temalandırma composable işlevi olan AppTheme()'yı da içerir.
Theme.kt
package com.example.reply.ui.theme
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.runtime.Composable
private val LightColors = lightColorScheme(
primary = md_theme_light_primary,
onPrimary = md_theme_light_onPrimary,
primaryContainer = md_theme_light_primaryContainer,
onPrimaryContainer = md_theme_light_onPrimaryContainer,
secondary = md_theme_light_secondary,
onSecondary = md_theme_light_onSecondary,
secondaryContainer = md_theme_light_secondaryContainer,
onSecondaryContainer = md_theme_light_onSecondaryContainer,
tertiary = md_theme_light_tertiary,
onTertiary = md_theme_light_onTertiary,
tertiaryContainer = md_theme_light_tertiaryContainer,
onTertiaryContainer = md_theme_light_onTertiaryContainer,
error = md_theme_light_error,
errorContainer = md_theme_light_errorContainer,
onError = md_theme_light_onError,
onErrorContainer = md_theme_light_onErrorContainer,
background = md_theme_light_background,
onBackground = md_theme_light_onBackground,
surface = md_theme_light_surface,
onSurface = md_theme_light_onSurface,
surfaceVariant = md_theme_light_surfaceVariant,
onSurfaceVariant = md_theme_light_onSurfaceVariant,
outline = md_theme_light_outline,
inverseOnSurface = md_theme_light_inverseOnSurface,
inverseSurface = md_theme_light_inverseSurface,
inversePrimary = md_theme_light_inversePrimary,
surfaceTint = md_theme_light_surfaceTint,
outlineVariant = md_theme_light_outlineVariant,
scrim = md_theme_light_scrim,
)
private val DarkColors = darkColorScheme(
primary = md_theme_dark_primary,
onPrimary = md_theme_dark_onPrimary,
primaryContainer = md_theme_dark_primaryContainer,
onPrimaryContainer = md_theme_dark_onPrimaryContainer,
secondary = md_theme_dark_secondary,
onSecondary = md_theme_dark_onSecondary,
secondaryContainer = md_theme_dark_secondaryContainer,
onSecondaryContainer = md_theme_dark_onSecondaryContainer,
tertiary = md_theme_dark_tertiary,
onTertiary = md_theme_dark_onTertiary,
tertiaryContainer = md_theme_dark_tertiaryContainer,
onTertiaryContainer = md_theme_dark_onTertiaryContainer,
error = md_theme_dark_error,
errorContainer = md_theme_dark_errorContainer,
onError = md_theme_dark_onError,
onErrorContainer = md_theme_dark_onErrorContainer,
background = md_theme_dark_background,
onBackground = md_theme_dark_onBackground,
surface = md_theme_dark_surface,
onSurface = md_theme_dark_onSurface,
surfaceVariant = md_theme_dark_surfaceVariant,
onSurfaceVariant = md_theme_dark_onSurfaceVariant,
outline = md_theme_dark_outline,
inverseOnSurface = md_theme_dark_inverseOnSurface,
inverseSurface = md_theme_dark_inverseSurface,
inversePrimary = md_theme_dark_inversePrimary,
surfaceTint = md_theme_dark_surfaceTint,
outlineVariant = md_theme_dark_outlineVariant,
scrim = md_theme_dark_scrim,
)
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
val colors = if (!useDarkTheme) {
LightColors
} else {
DarkColors
}
MaterialTheme(
colorScheme = colors,
content = content
)
}
Jetpack Compose'da tema oluşturmayı uygulamak için kullanılan temel öğe MaterialTheme composable'dır.
MaterialTheme() composable'ı, iki parametre alan AppTheme() işlevine sarmalarsınız:
useDarkTheme: Bu parametre, sistem tema ayarlarını gözlemlemek ve açık veya koyu temayı uygulamak içinisSystemInDarkTheme()işlevine bağlıdır. Uygulamanızı manuel olarak açık veya koyu temada tutmak istiyorsanızuseDarkThemeöğesine bir Boole değeri iletebilirsiniz.content- temanın uygulanacağı içerik.
Theme.kt
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
val colors = if (!useDarkTheme) {
LightColors
} else {
DarkColors
}
MaterialTheme(
colorScheme = colors,
content = content
)
}
Uygulamayı şimdi çalıştırmayı denerseniz aynı göründüğünü görürsünüz. Yeni tema renkleriyle yeni renk şemamızı içe aktarmış olsanız bile temayı Compose uygulamasına uygulamadığınız için temel tema özelliklerini görmeye devam ediyorsunuz.

Tema uygulanmadığında temel temalandırmaya sahip uygulama.
Yeni temayı uygulamak için MainActivity.kt içinde ana composable ReplyApp öğesini ana tema işlevi AppTheme() ile sarmalayın.
MainActivity.kt
setContent {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
AppTheme {
ReplyApp(/*..*/)
}
}
Ayrıca, temanın uygulama önizlemelerine uygulanmış halini görmek için önizleme işlevlerini de güncellersiniz. Temayı önizlemelere uygulamak için ReplyApp composable'ı ReplyAppPreview() içine AppTheme ile sarmalayın.
Önizleme parametrelerinde hem açık hem de koyu sistem temaları tanımlandığı için her iki önizlemeyi de görürsünüz.
MainActivity.kt
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
name = "DefaultPreviewDark"
)
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_NO,
name = "DefaultPreviewLight"
)
@Composable
fun ReplyAppPreview() {
AppTheme {
ReplyApp(
replyHomeUIState = ReplyHomeUIState(
emails = LocalEmailsDataProvider.allEmails
)
)
}
}
Uygulamayı şimdi çalıştırırsanız temel tema yerine içe aktarılan tema renkleriyle uygulama önizlemelerini görürsünüz.

Temel temalı uygulama (sol).
İçe aktarılmış renk teması olan uygulama (sağda).

İçe aktarılan renk temalarıyla açık ve koyu uygulama önizlemeleri.
Material 3 hem açık hem de koyu renk şemalarını destekler. Uygulamayı yalnızca içe aktarılan tema ile sarmışsınızdır. Material 3 bileşenleri varsayılan renk rollerini kullanıyordur.
Uygulamaya eklemeye başlamadan önce renk rolleri ve kullanımı hakkında bilgi edinelim.
Renk rolleri ve erişilebilirlik
Her renk rolü, bileşenin durumuna, belirginliğine ve vurgusuna bağlı olarak çeşitli yerlerde kullanılabilir.

Birincil, ikincil ve üçüncül renklerin renk rolleri.
Birincil, belirgin düğmeler ve etkin durumlar gibi ana bileşenlerde kullanılan temel renktir.
İkincil anahtar rengi, filtre çipleri gibi kullanıcı arayüzündeki daha az belirgin bileşenler için kullanılır.
Üçüncül ana renk, kontrastlı vurgular sağlamak için kullanılır. Uygulamadaki arka plan ve yüzeyler için ise nötr renkler kullanılır.
Malzemenin renk sistemi, erişilebilir kontrast oranlarını karşılamak için kullanılabilecek standart ton değerleri ve ölçümler sağlar. Kullanıcıya erişilebilir kontrast sağlamak için birincil rengin üzerinde on-primary, birincil kapsayıcının üzerinde on-primary-container ve diğer vurgu ve nötr renkler için de aynı şekilde kullanın.
Daha fazla bilgi için renk rolleri ve erişilebilirlik başlıklı makaleyi inceleyin.
Ton ve gölge yükseklikleri
Material 3, yüksekliği esas olarak ton rengi yer paylaşımlarıyla gösterir. Bu, gölgelere ek olarak, kapsayıcıları ve yüzeyleri birbirinden ayırmanın yeni bir yoludur. Ton yüksekliğini artırmak için daha belirgin bir ton kullanılır.
Birincil renk yuvasındaki rengi kullanan 2. düzeyde tonal yükseltme.
Koyu temalardaki yükseklik katmanları da Materyal Tasarım 3'te tonlu renk katmanlarına dönüştürüldü. Yer paylaşımı rengi, birincil renk yuvasından gelir.
Çoğu M3 bileşeninin temelini oluşturan M3 Surface, hem ton hem de gölge yüksekliği desteği içerir:
Surface(
modifier = modifier,
tonalElevation = {..}
shadowElevation = {..}
) {
Column(content = content)
}
Uygulamaya renk ekleme
Uygulamayı çalıştırırsanız bileşenlerin varsayılan renkleri kullandığı uygulamada dışa aktarılan renklerin gösterildiğini görebilirsiniz. Renk rolleri ve kullanımı hakkında bilgi sahibi olduğumuza göre şimdi uygulamayı doğru renk rolleriyle temalandıralım.

Varsayılan renk rollerini alan renk temalı ve bileşenli uygulama.
Yüzey renkleri
Ana ekranda, uygulamanın içeriğinin üzerine yerleştirileceği tabanı sağlamak için ana uygulama composable'ını Surface() ile sarmalayarak başlayacaksınız. MainActivity.kt öğesini açın ve ReplyApp() composable'ı Surface ile sarmalayın.
Ayrıca, yüzeye birincil yuvanın tonal rengini vermek için 5 dp'lik bir tonal yükseltme sağlayacaksınız.Bu, liste öğesi ve üzerindeki arama çubuğuyla kontrast oluşturmaya yardımcı olur. Varsayılan olarak, yüzeyin ton ve gölge yüksekliği 0 dp'dir.
MainActivity.kt
AppTheme {
Surface(tonalElevation = 5.dp) {
ReplyApp(
replyHomeUIState = uiState,
// other parameters
)
}
}
Uygulamanızı şimdi çalıştırıp hem liste hem de ayrıntı sayfasını görürseniz ton yüzeyinin uygulamanın tamamına uygulandığını görmeniz gerekir.

Yüzey ve ton rengi olmayan uygulama arka planı (sol).
Yüzey ve ton rengi uygulanmış uygulama arka planı (sağ).
Uygulama çubuğu renkleri
En üstteki özel arama çubuğumuz, tasarım isteklerine uygun olarak net bir arka plana sahip değil. Varsayılan olarak, varsayılan temel yüzeye geri döner. Net bir ayrım sağlamak için arka plan ekleyebilirsiniz.

Arka planı olmayan özel arama çubuğu (sol).
Arka planı olan özel arama çubuğu (sağ).
Artık uygulama çubuğunu içeren ui/components/ReplyAppBars.kt öğesini düzenleyeceksiniz. MaterialTheme.colorScheme.background adlı öğeyi Row Composable'ın Modifier adlı öğesine ekleyeceksiniz.
ReplyAppBars.kt
@Composable
fun ReplySearchBar(modifier: Modifier = Modifier) {
Row(
modifier = modifier
.fillMaxWidth()
.padding(16.dp)
.background(MaterialTheme.colorScheme.background),
verticalAlignment = Alignment.CenterVertically
) {
// Search bar content
}
}
Artık tonlu yüzey ile arka plan rengi olan uygulama çubuğu arasında net bir ayrım göreceksiniz.

Tonlu yüzeyin üzerinde arka plan rengi olan arama çubuğu.
Kayan işlem düğmesi renkleri

Tema uygulanmamış büyük FAB (sol).
Üçüncül renge sahip temalı büyük FAB (sağ).
Ana ekranda, kayan işlem düğmesinin (FAB) görünümünü iyileştirerek işlem çağrısı düğmesi olarak öne çıkmasını sağlayabilirsiniz. Bunu uygulamak için üçüncül bir vurgu rengi kullanırsınız.
Erişilebilirlik ve renk kontrastını korumak için ReplyListContent.kt dosyasında, FAB'ın containerColor özelliğini tertiaryContainer rengiyle, içerik rengini ise onTertiaryContainer rengiyle güncelleyin.
ReplyListContent.kt
ReplyInboxScreen(/*..*/) {
// Email list content
LargeFloatingActionButton(
containerColor = MaterialTheme.colorScheme.tertiaryContainer,
contentColor = MaterialTheme.colorScheme.onTertiaryContainer
){
/*..*/
}
}
FAB'ınızın temalı halini görmek için uygulamayı çalıştırın. Bu codelab'de LargeFloatingActionButton kullanıyorsunuz.
Kart renkleri
Ana ekrandaki e-posta listesinde kart bileşeni kullanılır. Varsayılan olarak, yüzey ve kart rengi arasında net bir ayrım sağlamak için kapsayıcı rengi olarak yüzey varyantı rengini kullanan bir dolu karttır. Compose ayrıca ElevatedCard ve OutlinedCard uygulamalarını da sağlar.
İkincil renk tonları sağlayarak önemli olan bazı öğeleri daha da vurgulayabilirsiniz. Önemli e-postalar için ui/components/ReplyEmailListItem.kt kullanarak kart kapsayıcı rengini güncelleyerek CardDefaults.cardColors() öğesini değiştirirsiniz:
ReplyEmailListItem.kt
Card(
modifier = modifier
.padding(horizontal = 16.dp, vertical = 4.dp)
.semantics { selected = isSelected }
.clickable { navigateToDetail(email.id) },
colors = CardDefaults.cardColors(
containerColor = if (email.isImportant)
MaterialTheme.colorScheme.secondaryContainer
else MaterialTheme.colorScheme.surfaceVariant
)
){
/*..*/
}

Tonlu yüzeyde ikincil kapsayıcı rengini kullanarak liste öğesini vurgulayın.
Ayrıntı listesi öğesinin rengi
Ana ekranınız artık temalı. E-posta listesi öğelerinden herhangi birini tıklayarak ayrıntılar sayfasına göz atın.

Temalı liste öğesi içermeyen varsayılan ayrıntılar sayfası (sol).
Arka plan teması uygulanmış ayrıntılı liste öğesi (sağ).
Liste öğenize herhangi bir renk uygulanmadığından varsayılan tonal yüzey rengine geri dönülüyor. Ayrım oluşturmak için liste öğesine arka plan rengi uygulayacak ve arka planımızın etrafında boşluk bırakmak için dolgu ekleyeceksiniz.
ReplyEmailThreadItem.kt
@Composable
fun ReplyEmailThreadItem(
email: Email,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.fillMaxWidth()
.padding(16.dp)
.background(MaterialTheme.colorScheme.background)
.padding(20.dp)
) {
// List item content
}
}
Yalnızca arka plan sağlayarak ton yüzeyi ile liste öğesi arasında net bir ayrım elde ettiğinizi görebilirsiniz.
Artık hem ana sayfa hem de ayrıntılar sayfası doğru renk rolleri ve kullanımıyla gösteriliyor . Uygulamanızın daha da kişiselleştirilmiş ve tutarlı bir deneyim sunmak için dinamik renklerden nasıl yararlanabileceğine bakalım.
5. Uygulamaya dinamik renkler ekleme
Dinamik renk, Material 3'ün temelini oluşturur. Bu tasarımda, bir algoritma kullanıcının duvar kağıdından özel renkler türetir ve bunları uygulamalarına ve sistem kullanıcı arayüzüne uygular.
Dinamik tema, uygulamalarınızı daha kişiselleştirilmiş hale getirir. Ayrıca, kullanıcıların sistem temasıyla tutarlı ve sorunsuz bir deneyim yaşamasını sağlar.
Dinamik renk, Android 12 ve sonraki sürümlerde kullanılabilir. Dinamik renk özelliği varsa dynamicDarkColorScheme() veya dynamicLightColorScheme() simgesini kullanarak dinamik bir renk şeması ayarlayabilirsiniz. Aksi takdirde, varsayılan açık veya koyu bir ColorScheme kullanmaya geri dönmeniz gerekir.
Theme.kt dosyasındaki AppTheme işlevinin kodunu aşağıdakiyle değiştirin:
Theme.kt
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val context = LocalContext.current
val colors = when {
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) -> {
if (useDarkTheme) dynamicDarkColorScheme(context)
else dynamicLightColorScheme(context)
}
useDarkTheme -> DarkColors
else -> LightColors
}
MaterialTheme(
colorScheme = colors,
content = content
)
}

Android 13 duvar kağıdından alınan dinamik tema.
Uygulamayı şimdi çalıştırdığınızda, varsayılan Android 13 duvar kağıdı kullanılarak dinamik temanın uygulandığını görmeniz gerekir.
Ayrıca, durum çubuğunun, uygulamanızı temalandırmak için kullanılan renk şemasına bağlı olarak dinamik şekilde stilize edilmesini de isteyebilirsiniz.

Durum çubuğu rengi uygulanmamış uygulama (sol).
Durum çubuğu rengi uygulanmış uygulama (sağda).
Durum çubuğu rengini temanızın birincil rengine göre güncellemek için AppTheme composable'da renk şeması seçiminden sonra durum çubuğu rengini ekleyin:
Theme.kt
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
// color scheme selection code
// Add primary status bar color from chosen color scheme.
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as Activity).window
window.statusBarColor = colors.primary.toArgb()
WindowCompat
.getInsetsController(window, view)
.isAppearanceLightStatusBars = useDarkTheme
}
}
MaterialTheme(
colorScheme = colors,
content = content
)
}
Uygulamayı çalıştırdığınızda durum çubuğunun birincil renk temanızı kullandığını görürsünüz. Sistemin koyu temasını değiştirerek hem açık hem de koyu dinamik temayı deneyebilirsiniz.

Android 13'ün varsayılan duvar kağıdıyla uygulanan dinamik açık (sol) ve koyu (sağ) tema.
Şimdiye kadar uygulamanıza, görünümünü iyileştiren renkler uyguladınız. Ancak uygulamadaki tüm metinlerin aynı boyutta olduğunu görebilirsiniz. Bu nedenle, uygulamaya artık tipografi ekleyebilirsiniz.
6. Yazı biçimi
Materyal Tasarım 3, tip ölçeğini tanımlar. Adlandırma ve gruplandırma şu şekilde basitleştirildi: görüntüleme, başlık, başlık, gövde ve etiket. Her biri için büyük, orta ve küçük boyutlar kullanılıyor.

Material 3 türü ölçeği.
Yazı karakterini tanımlama
Compose, Materyal 3 tür ölçeğini modellemek için mevcut TextStyle ve font-related sınıflarının yanı sıra M3 Typography sınıfını sağlar.
Typography oluşturucusu, her stil için varsayılan değerler sunar. Böylece özelleştirmek istemediğiniz parametreleri atlayabilirsiniz. Daha fazla bilgi için tipografi stilleri ve varsayılan değerleri konusuna bakın.
Uygulamanızda beş tipografi stili kullanacaksınız: headlineSmall, titleLarge, bodyLarge, bodyMedium ve labelMedium. Bu stiller hem ana ekranı hem de ayrıntı ekranını kapsar.

Başlık, etiket ve araç kasa tipi stilinin tipografi kullanımını gösteren ekran.
Ardından, ui/theme paketine gidip Type.kt dosyasını açın. Varsayılan değerler yerine bazı metin stilleri için kendi uygulamanızı sağlamak üzere aşağıdaki kodu ekleyin:
Type.kt
val typography = Typography(
headlineSmall = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 24.sp,
lineHeight = 32.sp,
letterSpacing = 0.sp
),
titleLarge = TextStyle(
fontWeight = FontWeight.Normal,
fontSize = 18.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
),
bodyLarge = TextStyle(
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.15.sp
),
bodyMedium = TextStyle(
fontWeight = FontWeight.Medium,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.25.sp
),
labelMedium = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 12.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
)
Tipografiniz tanımlandı. Temanıza eklemek için MaterialTheme() composable'ına AppTheme içinde iletin:
Theme.kt
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
// dynamic theming content
MaterialTheme(
colorScheme = colors,
typography = typography,
content = content
)
}
Tipografiyle çalışma
Renklerde olduğu gibi, MaterialTheme.typography simgesini kullanarak mevcut temanın tipografi stiline erişebilirsiniz. Bu, Type.kt içinde tanımlanan tüm tipografiyi kullanmak için tipografi örneğini verir.
Text(
text = "Hello M3 theming",
style = MaterialTheme.typography.titleLarge
)
Text(
text = "you are learning typography",
style = MaterialTheme.typography.bodyMedium
)
Ürününüz için Materyal Tasarım tür ölçeğindeki 15 varsayılan stilin tamamı muhtemelen gerekli olmayacaktır. Bu codelab'de beş boyut seçilirken diğerleri atlanmıştır.
Text() composable'larına tipografi uygulamadığınız için tüm metinler varsayılan olarak Typography.bodyLarge'a geri döner.
Ana sayfa listesi tipi
Ardından, başlıklar ve etiketler arasında ayrım yapmak için ui/components/ReplyEmailListItem.kt içindeki ReplyEmailListItem işlevine tipografi uygulayın:
ReplyEmailListItem.kt
Text(
text = email.sender.firstName,
style = MaterialTheme.typography.labelMedium
)
Text(
text = email.createdAt,
style = MaterialTheme.typography.labelMedium
)
Text(
text = email.subject,
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(top = 12.dp, bottom = 8.dp),
)
Text(
text = email.body,
maxLines = 2,
style = MaterialTheme.typography.bodyLarge,
overflow = TextOverflow.Ellipsis
)

Tipografi uygulanmamış ana ekran (sol).
Tipografinin uygulandığı ana ekran (sağ).
Ayrıntı listesi tipografisi
Benzer şekilde, ReplyEmailThreadItem'nın tüm metin composable'larını ui/components/ReplyEmailThreadItem.kt içinde güncelleyerek ayrıntı ekranına tipografiyi ekleyeceksiniz:
ReplyEmailThreadItem.kt
Text(
text = email.sender.firstName,
style = MaterialTheme.typography.labelMedium
)
Text(
text = stringResource(id = R.string.twenty_mins_ago),
style = MaterialTheme.typography.labelMedium
)
Text(
text = email.subject,
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(top = 12.dp, bottom = 8.dp),
)
Text(
text = email.body,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
)

Yazı biçimi uygulanmamış ayrıntı ekranı (sol).
Yazı biçimi uygulanmış ayrıntı ekranı (sağda).
Tipografiyi özelleştirme
Compose ile metin stilinizi özelleştirmek veya özel yazı tipinizi sağlamak çok kolaydır. Yazı tipi türünü, yazı tipi ailesini, harf aralığını vb. özelleştirmek için TextStyle öğesini değiştirebilirsiniz.
theme/Type.kt dosyasındaki metin stilini değiştirdiğinizde bu değişiklik, dosyayı kullanan tüm bileşenlere yansıtılır.
Liste öğesindeki konu için kullanılan titleLarge hizmetinde fontWeight öğesini SemiBold, lineHeight öğesini ise 32.sp olarak güncelleyin. Bu, konuyu daha fazla vurgular ve net ayrımlar sağlar.
Type.kt
...
titleLarge = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 18.sp,
lineHeight = 32.sp,
letterSpacing = 0.0.sp
),
...

Konu metnine özel tipografi uygulama.
7. Şekiller
Material yüzeyleri farklı şekillerde gösterilebilir. Şekiller, dikkati yönlendirir, bileşenleri tanımlar, durumu bildirir ve markayı ifade eder.
Şekil tanımlama
Compose, yeni M3 şekillerini uygulamak için genişletilmiş parametrelerle Shapes sınıfını sağlar. Tip ölçeğine benzer olan M3 şekil ölçeği, kullanıcı arayüzünde etkileyici bir şekil aralığı sağlar.
Şekil ölçeğinde farklı boyutlarda şekiller bulunur:
- Çok küçük
- Küçük
- Orta zorlukta
- Büyük
- Çok büyük
Varsayılan olarak her şeklin geçersiz kılınabilen bir varsayılan değeri vardır. Uygulamanız için liste öğesini değiştirmek üzere orta şekli kullanırsınız ancak diğer şekilleri de bildirebilirsiniz. ui/theme paketinde Shape.kt adlı yeni bir dosya oluşturun ve şekiller için kodu ekleyin:
Shape.kt
package com.example.reply.ui.theme
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Shapes
import androidx.compose.ui.unit.dp
val shapes = Shapes(
extraSmall = RoundedCornerShape(4.dp),
small = RoundedCornerShape(8.dp),
medium = RoundedCornerShape(16.dp),
large = RoundedCornerShape(24.dp),
extraLarge = RoundedCornerShape(32.dp)
)
shapes öğenizi tanımladığınıza göre, renkler ve tipografide yaptığınız gibi M3 MaterialTheme öğesine iletin:
Theme.kt
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
// dynamic theming content
MaterialTheme(
colorScheme = colors,
typography = typography,
shapes = shapes
content = content
)
}
Şekillerle çalışma
Renk ve tipografide olduğu gibi, MaterialTheme.shape kullanarak şekilleri Material bileşenlerine uygulayabilirsiniz. Bu sayede Material şekillerine erişmek için Shape örneğini elde edersiniz.
Birçok Material bileşenine varsayılan şekiller uygulanmıştır ancak kullanılabilir yuvalar aracılığıyla bileşenlere kendi şekillerinizi sağlayıp uygulayabilirsiniz.
Card(shape = MaterialTheme.shapes.medium) { /* card content */ }
FloatingActionButton(shape = MaterialTheme.shapes.large) { /* fab content */}
Farklı şekil türleri kullanılarak Materyal bileşenlerinin eşlenmesi.
Tüm bileşenlerin şekil eşlemesini Şekil dokümanında görebilirsiniz.
Oluşturma özelliğinin bir parçası olan RectangleShape ve CircleShape olmak üzere kullanabileceğiniz iki şekil daha vardır. Dikdörtgen şeklin kenar yarıçapı yok ve daire şeklinin kenarları tamamen yuvarlak.
Ayrıca, Modifier.clip, Modifier.background ve Modifier.border gibi şekil alan Modifiers kullanarak bileşenlerinize şekil uygulayabilirsiniz.
Uygulama çubuğu şekli
Uygulama çubuğunun yuvarlak köşeli bir arka planı olmasını istiyoruz:

TopAppBar, arka plan rengi olan bir Row kullanıyor. Yuvarlak köşeli arka plan elde etmek için arka plan değiştiriciye CircleShape değerini ileterek arka planın şeklini tanımlayın:
ReplyAppBars.kt
@Composable
fun ReplySearchBar(modifier: Modifier = Modifier) {
Row(
modifier = modifier
.fillMaxWidth()
.padding(16.dp)
.background(
MaterialTheme.colorScheme.background,
CircleShape
),
verticalAlignment = Alignment.CenterVertically
) {
// Search bar content
}
}

Ayrıntı liste öğesi şekli
Ana ekranda, varsayılan olarak Shape.Medium kullanan bir kart kullanıyorsunuz. Ancak ayrıntı sayfamız için bunun yerine arka plan rengi olan bir sütun kullandınız. Listenin görünümünün tek tip olması için orta şekil uygulayın.

Liste öğesinde şekil olmayan (sol) ve listede orta şekil olan (sağ) ayrıntılı liste öğesi sütunu.
ReplyEmailThreadItem.kt
@Composable
fun ReplyEmailThreadItem(
email: Email,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.fillMaxWidth()
.padding(8.dp)
.background(
MaterialTheme.colorScheme.background,
MaterialTheme.shapes.medium
)
.padding(16.dp)
) {
// List item content
}
}
Artık uygulamanızı çalıştırdığınızda medium şeklinde ayrıntılı bir ekran listesi öğesi gösteriliyor.
8. Vurgu
Kullanıcı arayüzündeki vurgu, başlığı altyazılardan ayırmak istediğinizde olduğu gibi bazı içerikleri diğerlerinden daha fazla öne çıkarmanıza yardımcı olur. M3'te vurgu için renk varyasyonları ve renk kombinasyonları kullanılır. Vurgu eklemenin iki yolu vardır:
- Genişletilmiş M3 renk sistemindeki yüzey, yüzey varyantı ve arka plan renklerini, yüzeydeki ve yüzeydeki varyant renkleriyle birlikte kullanma.
Örneğin, farklı vurgu düzeyleri sağlamak için surface, on-surface-variant ile, surface-variant ise on-surface ile kullanılabilir.
Yüzey varyantları, vurgu renkleriyle birlikte de kullanılabilir. Bu sayede, vurgu renklerine kıyasla daha az vurgu sağlanır ancak yine de erişilebilir ve kontrast oranına uygun olur.

Yüzey, arka plan ve yüzey varyantı renk rolleri.
- Metin için farklı yazı tipi ağırlıkları kullanma. Tipografi bölümünde gördüğünüz gibi, farklı vurgular sağlamak için tür ölçeğinize özel ağırlıklar verebilirsiniz.
Ardından, yüzey varyantını kullanarak vurgu farkı sağlamak için ReplyEmailListItem.kt öğesini güncelleyin. Varsayılan olarak, kartın içeriği arka plana bağlı olarak varsayılan içerik rengini alır.
Zaman metni ve gövde metni composable'ının rengini onSurfaceVariant olarak güncelleyeceksiniz. Bu, konu ve başlık metni composable'larına varsayılan olarak uygulanan onContainerColors ile karşılaştırıldığında vurguyu azaltır.

Konu ve başlığa kıyasla aynı vurguya sahip saat ve gövde metni (sol).
Konu ve başlığa kıyasla daha az vurgulanmış saat ve gövde (sağ).
ReplyEmailListItem.kt
Text(
text = email.createdAt,
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = email.body,
maxLines = 2,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
overflow = TextOverflow.Ellipsis
)
Arka planı secondaryContainer olan önemli e-posta kartında tüm metin rengi varsayılan olarak onSecondaryContainer olur. Diğer e-postalarda arka plan surfaceVariant, olduğundan tüm metinler varsayılan olarak onSurfaceVariant renkte gösterilir.
9. Tebrikler
Tebrikler! Bu codelab'i başarıyla tamamladınız. Uygulamanızı temalandırmak ve kişiselleştirilmiş bir deneyim sunmak için dinamik renklerin yanı sıra renkler, tipografi ve şekiller kullanarak Compose ile Material temalandırmayı uyguladınız.

Dinamik renkler ve renk teması uygulanmış temalandırma sonuçlarının sonu.
Sırada ne var?
Compose rotasındaki diğer codelab'lerimize göz atın:
- Oluşturma ile İlgili Temel Bilgiler
- Compose düzenleri
- Compose'da durum
- Mevcut Uygulamalar İçin Compose
Daha fazla bilgi
- Compose tema kılavuzu
- Compose için Materyal Teması Oluşturma
Örnek uygulamalar
- Tam Material 3 teması içeren yanıt örneği uygulaması
- Dinamik temayı gösteren JetChat