Compose'da Materyal 3 ile tema oluşturma

1. Giriş

Bu codelab'de, Materyal Tasarım 3'ü kullanarak Jetpack Compose'da uygulamalarınız için tema oluşturma hakkında bilgi edineceksiniz. Ayrıca, uygulamanıza kişiselleştirilmiş ve erişilebilir şekillerde tema yapmanıza yardımcı olan Materyal Tasarım 3'ün temel yapı taşları, renk şemaları, tipografi ve şekiller hakkında da bilgi edineceksiniz.

Buna ek olarak, farklı vurgu seviyeleriyle birlikte dinamik tema oluşturma desteğini keşfedeceksiniz.

Öğrenecekleriniz

Bu codelab'de şunları öğreneceksiniz:

  • Materyal 3 teması oluşturmanın temel yönleri
  • Malzeme 3 renk şemaları ve uygulamanız için tema oluşturma
  • Uygulamanızda dinamik ve açık/koyu temayı destekleme
  • Uygulamanızı kişiselleştirmek için yazı biçimi ve şekiller
  • Materyal 3 bileşenleri ve uygulamanızın stilini belirlemek için özelleştirme

Ne oluşturacaksınız?

Bu codelab'de, Yanıtla adlı bir e-posta istemci uygulaması oluşturacaksınız. Temel temayı kullanarak, stilsiz bir uygulamayla başlarsınız. Öğrendiklerinizi, uygulamaya tema uygulamak ve koyu temaları desteklemek için uygularsınız.

d15db3dc75a9d00f.png

Uygulamamızın varsayılan temaya sahip varsayılan başlangıç noktası.

Temanızı renk şeması, yazı biçimi ve şekillerle oluşturup uygulamanızın e-posta listesi ve ayrıntılar sayfasına uygularsınız. Ayrıca uygulamaya dinamik tema desteği de ekleyeceksiniz. Codelab'in sonunda uygulamanız için hem renk hem de dinamik temalar desteği olacak.

1357cdbfaaa67721.png

Açık renk teması ve açık dinamik tema içeren tema oluşturma codelab'inin bitiş noktası.

1357cdbfaaa67721.png

Koyu renk teması ve koyu dinamik temaya sahip tema oluşturma codelab'inin bitiş noktası.

Gerekenler

2. Kurulum

Bu adımda, bu codelab'de stilini belirleyeceğiniz Reply uygulamasının tam kodunu indireceksiniz.

Kodu alın

Bu codelab'in koduna android-compose-codelabs GitHub deposunda ulaşabilirsiniz. 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 atın

İndirdiğiniz kod, mevcut tüm Compose codelab'leri için kod 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. İstediğiniz zaman projenin git dalını değiştirerek Android Studio'da her iki sürümü de çalıştırabilirsiniz.

Başlangıç kodunu keşfetme

Ana kod, aşağıdaki ana paketlere ve etkileşimde bulunacağınız dosyalara sahip bir kullanıcı arayüzü paketi içerir:

  • MainActivity.kt – Yanıtlama uygulamasını başlattığınız giriş noktası etkinliği.
  • com.example.reply.ui.theme – Bu paket temalar, tipografi ve renk şemaları içerir. Bu pakete Materyal teması ekleyeceksiniz.
  • com.example.reply.ui.components - Liste Öğeleri, Uygulama Çubukları gibi uygulamanın özel bileşenlerini içerir. Bu bileşenlere tema uygularsınız.
  • ReplyApp.kt: Bu, kullanıcı arayüzü ağacının başlayacağı ana Oluşturulabilir işlevimizdir. Bu dosyada üst düzey tema uygulayacaksınız.

Bu codelab, ui paket dosyasına odaklanmaktadır.

3. Malzeme 3 Teması

Jetpack Compose, dijital arayüzler oluşturmak için kapsamlı bir tasarım sistemi olan Materyal Tasarım'ın uygulanmasını sunuyor. Materyal Tasarım bileşenleri (Düğmeler, Kartlar, Anahtarlar vb.), Malzeme Temaları temel alınarak oluşturulmuştur. Materyal Tasarım, ürününüzün markasını daha iyi yansıtacak şekilde Materyal Tasarım'ı özelleştirmenin sistematik bir yoludur.

Materyal 3 teması, uygulamanıza tema eklemek için kullanabileceğiniz şu alt sistemleri içerir: 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 alt sistemi ayrıntılı bir şekilde inceleyelim ve örnek uygulamaya uygulayalım.

Materyal tasarımın alt sistemleri: Renk, Tipografi ve Şekiller.

Renkler, tipografi ve şekillerden oluşan Materyal 3 alt sistemi.

4. Renk şemaları

Renk şemasının temeli, her biri 13 tonluk bir ton paletine ilişkin olan beş temel renk kümesidir. Bu renkler, Malzeme 3 bileşenlerinde kullanılır.

M3 teması oluşturmak için beş temel temel renk.

M3 teması oluşturmak için beş temel temel renk.

Ardından her vurgu rengi (birincil, ikincil ve üçüncül), eşleme, vurguyu tanımlama ve görsel ifade için farklı tonlarda dört uyumlu renkle sağlanır.

Birincil, ikincil ve üçüncül temel vurgu renklerinin dört ton rengi.

Birincil, ikincil ve üçüncül temel vurgu renklerinin dört ton rengi.

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

Temel nötr renklerin dört ton rengi.

Temel nötr renklerin dört ton rengi.

Renk şeması ve renk rolleri hakkında daha fazla bilgi edinin.

Renk şemaları oluşturuluyor

Manuel olarak özel bir ColorScheme oluşturabilirsiniz ancak markanızın kaynak renklerini kullanarak bir özel renk oluşturmak genellikle daha kolaydır. Materyal Tema Oluşturucu aracı bunu yapmanıza ve isteğe bağlı olarak Oluşturma tema kodunu dışa aktarmanıza olanak tanır.

İstediğiniz rengi seçebilirsiniz, ancak bizim kullanım örneğimiz için varsayılan Yanıtla birincil rengini #825500 kullanacaksınız. Soldaki Temel renkler bölümünde Birincil renk'i tıklayın ve renk seçiciye kodu ekleyin.

294f73fc9d2a570e.png

Material Theme Builder'a birincil renk kodu ekleniyor.

Material Theme Builder'da birincil rengi ekledikten sonra sağ üst köşede aşağıdaki temayı ve dışa aktarma seçeneğini göreceksiniz. Bu codelab'de temayı Jetpack Compose'da dışa aktaracaksınız.

Sağ üst köşede dışa aktarma seçeneği sunan Materyal Tema Oluşturucu.

Sağ üst köşede dışa aktarma seçeneği sunan Materyal Tema Oluşturucu.

#825500 birincil renk, uygulamaya ekleyeceğiniz aşağıdaki temayı oluşturur. Malzeme 3, bir bileşenin durumunu, belirginliğini ve vurgusunu esnek bir şekilde ifade etmek için çok çeşitli renk rolleri sunar.

Birincil renkteki Açık ve Koyu renk şeması dışa aktarıldı.

Birincil renkteki açık ve koyu renk şeması dışa aktarıldı.

Oluşturulan The Color.kt dosyası, 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)

Oluşturulan The Theme.kt dosya, açık ve koyu renk şemaları ile uygulama teması kurulumu içeriyor. Ayrıca, AppTheme() ana tema composable işlevini de 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şturmanın temel öğesi 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çin isSystemInDarkTheme() işlevine bağlıdır. Uygulamanızı manuel olarak açık veya koyu bir temada tutmak istiyorsanız useDarkTheme öğesine bir boole değeri aktarabilirsiniz.
  • 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öreceksiniz. Yeni renk şemamızı yeni tema renkleriyle içe aktarmış olsanız bile, Compose uygulamasına temayı uygulamadığınız için temel temayı görmeye devam edersiniz.

Tema uygulanmadığında, temel tema içeren uygulama.

Tema uygulanmadığında temel temaya sahip uygulama.

Yeni temayı uygulamak için MainActivity.kt ürününde ana composable ReplyApp öğesini, ana tema işlevi olan AppTheme() ile sarmalayın.

MainActivity.kt

setContent {
   val uiState by viewModel.uiState.collectAsStateWithLifecycle()

   AppTheme {
       ReplyApp(/*..*/)
   }
}

Ayrıca, uygulama önizlemelerine uygulanan temayı görmek için önizleme işlevlerini de güncelleyeceksiniz. Önizlemelere tema uygulamak için ReplyApp composable'ı ReplyAppPreview() içindeki AppTheme ile sarmalayın.

Önizleme parametrelerinde hem açık hem de koyu sistem temaları tanımlı olduğundan her iki önizlemeyi de göreceksiniz.

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ı şu anda çalıştırırsanız uygulama önizlemelerini temel tema yerine içe aktarılmış tema renkleriyle görmeniz gerekir.

fddf7b9cc99b1fe3.png be7a661b4553167b.png

Temel temaya sahip uygulama (Sol).

İçe aktarılan renk temasına sahip uygulama (Sağ).

674cec6cc12db6a0.png

İçe aktarılan renk temalarına sahip açık ve koyu uygulama önizlemeleri.

Malzeme 3, hem açık hem de koyu renk şemalarını destekler. Uygulamayı yalnızca içe aktarılan temayla sarmaladıysanız; Materyal 3 bileşenleri, varsayılan renk rollerini kullanıyor.

Uygulamaya eklemeden önce renk rolleri ve kullanımları hakkında bilgi edinelim.

Renk rolleri ve erişilebilirlik

Her bir renk rolü; bileşenin durumuna, belirginliğine ve vurgusuna bağlı olarak çeşitli yerlerde kullanılabilir.

1f184a05ea57aa84.png

Birincil, ikincil ve üçüncül renklerin renk rolleri.

Birincil, belirgin düğmeler ve etkin durumlar gibi ana bileşenler için kullanılan temel renktir.

İkincil anahtar rengi, kullanıcı arayüzünde filtre çipleri gibi daha az belirgin bileşenler için kullanılır.

Üçüncül anahtar rengi, zıt vurgular sağlamak için, arka plan ve uygulama yüzeyleri için 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, birincil kapsayıcının üstünde birincil, diğer vurgulu ve nötr renkler için de aynısını kullanın.

Daha fazla bilgi için renk rolleri ve erişilebilirlik konusuna bakın.

Ton ve gölge yüksekliği

Malzeme 3, genel olarak tonal renk yer paylaşımları kullanılarak yüksekliği temsil eder. Bu, kapsayıcılarla yüzeyleri birbirinden ayırt etmenin yeni bir yoludur. Ton yüksekliği artırıldığında gölgelere ek olarak daha belirgin bir ton kullanılır.

Gölge yüksekliğiyle birlikte ton rakımı Birincil renk alanından renk alan 2.seviyedeki ton yüksekliği

Materyal Tasarım 3'te, koyu temalardaki yükseklik yer paylaşımları da ton rengi yer paylaşımları olarak değiştirildi. Yer paylaşımı rengi, birincil renk alanından gelir.

Çoğu M3 bileşeninin arkasındaki composable olan M3 Yüzey, hem ton hem de gölge yükseltmesini destekler:

Surface(
   modifier = modifier,
   tonalElevation = {..}
   shadowElevation = {..}
) {
   Column(content = content)
}

Uygulamaya renk ekleniyor

Uygulamayı çalıştırırsanız dışa aktarılan renklerin, bileşenlerin varsayılan renkleri aldığı uygulamada gösterildiğini görebilirsiniz. Artık renk rollerini ve kullanımını öğrendiğimize göre uygulamaya doğru renk rolleriyle tema ekleyelim.

be7a661b4553167b.png

Renk teması ve bileşenlerin varsayılan renk rollerini alan uygulama.

Yüzey renkleri

Ana ekranda, composable'ı Surface() içine alarak uygulama içeriği için temel oluşturur, böylece uygulama içeriğinin üzerine yerleştirileceksiniz. MainActivity.kt öğesini açın ve ReplyApp() composable'ı Surface ile sarmalayın.

Ayrıca, yüzeye birincil yuvanın ton rengini vermek için 5.dp ton yüksekliği sağlarsınız. Bu, liste öğesi ve üstündeki 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ılar sayfasını görürseniz ton yüzeyinin uygulamanın tamamına uygulandığını görürsünüz.

be7a661b4553167b.png e70d762495173610.png

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ğumuzun, tasarım isteğinde belirtildiği gibi net bir arka planı yok. Varsayılan olarak, varsayılan taban yüzeyine geri döner. Ayrımı açıkça belirtmek için bir arka plan sağlayabilirsiniz.

5779fc399d8a8187.png

Arka planı olmayan özel arama çubuğu (Sol).

Arka planı olan özel arama çubuğu (Sağ).

Şimdi, uygulama çubuğunu içeren ui/components/ReplyAppBars.kt öğesini düzenleyeceksiniz. MaterialTheme.colorScheme.background öğesini Row Composable'ın Modifier öğ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
   }
}

Şimdi, arka plan rengiyle birlikte ton yüzeyi ile uygulama çubuğu arasında net bir ayrım görmeniz gerekir.

b1b374b801dadc06.png

Ton yüzeyinin üstünde arka plan rengi olan arama çubuğu.

Kayan işlem düğmesi renkleri

70ceac87233fe466.png

Tema uygulanmamış büyük FAB (Sol).

Üçüncül renkli temaya sahip büyük FAB (Sağ).

Ana ekrandaki kayan işlem düğmesinin (FAB) görünümünü iyileştirerek harekete geçirici mesaj düğmesi olarak öne çıkarabilirsiniz. Bunu uygulamak için, ona üçüncül bir vurgu rengi uygulayın.

Erişilebilirlik ile renk kontrastını korumak için ReplyListContent.kt dosyasında FAB'nin containerColor rengini tertiaryContainer, içerik rengini ise onTertiaryContainer olarak güncelleyin.

ReplyListContent.kt

ReplyInboxScreen(/*..*/) {
// Email list content
  LargeFloatingActionButton(
    containerColor = MaterialTheme.colorScheme.tertiaryContainer,
    contentColor = MaterialTheme.colorScheme.onTertiaryContainer
  ){
   /*..*/   
  }
}

FAB temanızı görmek için uygulamayı çalıştırın. Bu codelab için LargeFloatingActionButton kullanıyorsunuz.

Kart renkleri

Ana ekrandaki e-posta listesi bir kart bileşeni kullanır. Varsayılan olarak, yüzey ve kart rengi arasında net bir ayrım sağlamak amacıyla kapsayıcı rengi için yüzey varyantı rengini kullanan dolgulu kart kullanılır. Compose, ElevatedCard ve OutlinedCard uygulamalarını da sağlar.

İkincil renk tonları kullanarak önemli bazı öğeleri de vurgulayabilirsiniz. Önemli e-postalar için CardDefaults.cardColors() ile kart kapsayıcı rengini güncelleyerek ui/components/ReplyEmailListItem.kt öğesini değiştireceksiniz:

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
   )
){
  /*..*/   
}

5818200be0b01583.png 9367d40023db371d.png

Ton yüzeyinde ikincil kapsayıcı rengini kullanarak liste öğesini vurgulayın.

Ayrıntı listesi öğe rengi

Artık ana ekranınızın temasını belirlediniz. E-posta listesi öğelerinden herhangi birini tıklayarak ayrıntılar sayfasına göz atın.

7a9ea7cf3e91e9c7.png 79b3874aeca4cd1.png

Temalı liste öğesi içermeyen varsayılan ayrıntı sayfası (Sol).

Arka plan teması uygulanmış ayrıntı listesi öğesi (sağ).

Liste öğenize herhangi bir renk uygulanmadığından varsayılan ton yüzey rengi kullanılır. Ayırmak için liste öğesine arka plan rengi uygulayacak ve arka planımızda boşluk bırakacak 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 bir arka plan sağladığınızda, ton yüzeyi ile liste öğesi arasında net bir ayrım olduğunu görebilirsiniz.

Artık doğru renk rollerine ve kullanımına sahip hem ana sayfa hem de ayrıntı sayfalarınız var . Uygulamanızın, daha da kişiselleştirilmiş ve tutarlı bir deneyim sunmak için dinamik renklerden nasıl yararlanabileceğini inceleyelim.

5. Uygulamaya dinamik renkler ekleme

Dinamik renk, Materyal 3'ün önemli bir parçasıdır. Bir algoritma, kullanıcının uygulamalarına ve sistem kullanıcı arayüzüne uygulanacak duvar kağıdından özel renkler elde eder.

Dinamik tema, uygulamalarınızı daha kişisel hale getirir. Ayrıca kullanıcılara sistem temasıyla uyumlu ve sorunsuz bir deneyim sunar.

Dinamik renk özelliği Android 12 ve sonraki sürümlerde kullanılabilir. Dinamik renk kullanılabiliyorsa dynamicDarkColorScheme() veya dynamicLightColorScheme() kullanarak dinamik renk şeması oluşturabilirsiniz. Değilse varsayılan açık veya koyu renkli ColorScheme özelliğini kullanmanız 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
     )
}

fecc63b4c6034236.png

Android 13 duvar kağıdından alınan dinamik tema.

Uygulamayı şu anda çalıştırdığınızda varsayılan Android 13 duvar kağıdı kullanılarak dinamik temanın uygulandığını görürsünüz.

Durum çubuğunun, uygulamanızın temasını belirlemek için kullanılan renk şemasına bağlı olarak dinamik bir şekilde biçimlendirilmesini de isteyebilirsiniz.

1095e2b2c1ffdc14.png

Durum çubuğu rengi uygulanmayan uygulama (Sol).

Durum çubuğu rengi uygulanmış uygulama (Sağ).

Temanızın birincil rengine bağlı olarak durum çubuğu rengini güncellemek için AppTheme composable'daki 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ı aldığını görürsünüz. Sistem koyu temasını değiştirerek hem açık hem de koyu dinamik tema oluşturmayı deneyebilirsiniz.

69093b5bce31fd43.png

Android 13 varsayılan duvar kağıdıyla uygulanan dinamik açık (sol) ve koyu (sağ) tema.

Şimdiye kadar uygulamanıza renkler uygulayarak uygulamanın görünümünü iyileştirdiniz. Ancak, uygulamadaki tüm metinlerin aynı boyutta olduğunu gördüğünüzde, artık uygulamaya yazı biçimi ekleyebilirsiniz.

6. Yazı biçimi

Materyal Tasarım 3, bir tür ölçeği tanımlar. Adlandırma ve gruplandırma; görüntülü reklam, başlık, başlık, gövde ve etiket boyutlarının her biri büyük, orta ve küçük boyutlarda olacak şekilde basitleştirildi.

999a161dcd9b0ec4.png

Malzeme 3 türü ölçek.

Tipografiyi tanımlama

Compose, Materyal 3 türü ölçeği modellemek için mevcut TextStyle ve font-related sınıflarıyla birlikte M3 Typography sınıfını sağlar.

Tipografi oluşturucu, her stil için varsayılan ayarlar sunar. Böylece, özelleştirmek istemediğiniz parametreleri atlayabilirsiniz. Daha fazla bilgi için yazı stilleri ve varsayılan değerlerine 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ı kaplar.

Başlık, etiket ve gövde stilinin tipografik kullanımını gösteren ekran.

Başlık, etiket ve gövde stilinin tipografik kullanımını gösteren ekran.

Daha sonra, 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 artık tanımlanmış. Bunu temanıza eklemek için AppTheme içindeki MaterialTheme() composable'a 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 kullanarak geçerli temanın tipografi stiline de erişebilirsiniz. Bu şekilde, Type.k içinde tanımlanan tüm yazı biçimlerini kullanmanız için tipografi örneği elde edilir.

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 muhtemelen Materyal Tasarım türü ölçeğindeki 15 varsayılan stilin tamamına ihtiyaç duymayacaktır. Bu codelab'de beş boyut seçilirken diğerleri atlanır.

Text() composable'lara tipografi uygulamadığınız için tüm metinler varsayılan olarak Typography.bodyLarge ürününe döner.

Ana sayfa listesi tipografisi

Ardından, başlıklar ve etiketler arasında ayrım oluşturmak 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
)

90645c0765167bb7.png 6c4af2f412c18bfb.png

Tipografi uygulanmadan ana ekran (Sol).

Yazı biçimi uygulanmış ana ekran (sağ).

Ayrıntı listesi tipografisi

Benzer şekilde, ui/components/ReplyEmailThreadItem.kt dilindeki tüm ReplyEmailThreadItem metin composable'larını güncelleyerek ayrıntı ekranına yazı tipi 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
)

543ac09e43d8761.png 3412771e95a45f36.png

Yazı biçimi uygulanmamış ayrıntı ekranı (Sol).

Yazı biçimi uygulanmış ayrıntı ekranı (sağ).

Tipografiyi özelleştirme

Oluşturma özelliğiyle 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ştirmeniz, metni kullanan tüm bileşenlere de yansıtılır.

Liste öğesindeki konu için kullanılan titleLarge için fontWeight değerini SemiBold ve lineHeight değerini 32.sp olarak güncelleyin. Konuya daha fazla vurgu yapar ve bölümleri net bir şekilde ayırır.

Type.kt

...
titleLarge = TextStyle(
   fontWeight = FontWeight.SemiBold,
   fontSize = 18.sp,
   lineHeight = 32.sp,
   letterSpacing = 0.0.sp
),
...

f8d2212819eb0b61.png

Konu metnine özel tipografi uygulama.

7. Şekiller

Malzeme yüzeyleri farklı şekillerde gösterilebilir. Doğrudan dikkati şekillendirir, bileşenleri belirler, durumu bildirir ve markayı ifade eder.

Şekil tanımlama

Compose, yeni M3 şekillerini uygulamak için Shapes sınıfına genişletilmiş parametreler sağlar. Tür ölçeğine benzer şekilde M3 şekil ölçeği, kullanıcı arayüzünde anlamlı bir şekil aralığı sağlar.

Şekil ölçeğinde farklı boyutlarda şekiller vardır:

  • Çok küçük
  • Küçük
  • Aracı
  • Büyük
  • Çok büyük

Varsayılan olarak her şeklin geçersiz kılınabilecek bir varsayılan değeri vardır. Uygulamanızda, liste öğesini değiştirmek için orta şekli kullanırsınız, ancak başka şekilleri de bildirebilirsiniz. ui/theme paketinde Shape.kt adında yeni bir dosya oluşturun ve şekillere ilişkin 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 tipografiyle ilgili olarak yaptığınız gibi M3 MaterialTheme'e aktarın:

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

Tıpkı renk ve tipografide olduğu gibi, MaterialTheme.shape kullanarak Materyal bileşenlerine şekil uygulayabilirsiniz. Bu sayede, Materyal şekillere erişmek için Shape örneği elde edebilirsiniz.

Birçok Materyal bileşenine halihazırda uygulanmış varsayılan şekiller vardır ancak kendi şekillerinizi, mevcut alanlar aracılığıyla bileşenlere sağlayabilir ve uygulayabilirsiniz.

Card(shape = MaterialTheme.shapes.medium) { /* card content */ }
FloatingActionButton(shape = MaterialTheme.shapes.large) { /* fab content */}

Tüm Materyal 3 bileşenleri için varsayılan şekil değerleri.Farklı şekil türleri kullanarak Materyal bileşenlerinin eşlenmesi.

Şekil belgelerinde tüm bileşenler için şekillerin eşlenmesini görebilirsiniz.

Oluşturmanın parçası olan iki şekil daha (RectangleShape ve CircleShape) kullanılabilir. Dikdörtgen şeklinin kenarlık yarıçapı yoktur ve daire şekli, tam daire içine alınmış kenarları gösterir.

Modifier.clip, Modifier.background ve Modifier.border gibi şekiller alan Modifiers kullanarak da Bileşenlerinize şekil uygulayabilirsiniz.

Uygulama çubuğu şekli

Uygulama çubuğunun yuvarlatılmış bir arka plana sahip olmasını istiyoruz:

f873392abe535494.png

TopAppBar, arka plan rengi olan bir Row kullanıyor. Köşeleri yuvarlatılmış arka planı elde etmek için CircleShape komutunu arka plan değiştiriciye geçirerek 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
   }
}

f873392abe535494.png

Ayrıntı listesi öğesi şekli

Ana ekranda varsayılan olarak Shape.Medium kullanan bir kart kullanıyorsunuz. Ancak ayrıntılar sayfamız için bunun yerine arka plan rengi olan bir Sütun kullandınız. Listenin tek tip bir görünümü için orta şekilli bir liste görünümü uygulayın.

3412771e95a45f36.png 80ee881c41a98c2a.png

Liste öğesinde şekil olmayan (Sol) ve listede orta şekil (Sağ) olan ayrıntı listesi öğ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
      
   }
}

Şimdi, uygulamanızı çalıştırdığınızda size medium şeklinde ayrıntılı bir ekran listesi öğesi gösterilir.

8. Vurgu

Kullanıcı arayüzündeki vurgu, bazı içerikleri diğerinin üzerinde vurgulamanıza yardımcı olur. Örneğin, başlığın altyazıdan ayırt edilebilmesi için bu seçeneği kullanabilirsiniz. M3'teki Vurgu, farklı renk çeşitlerini ve renk üzerindeki kombinasyonlarını kullanır. Vurgu eklemenin iki yolu vardır:

  1. Genişletilmiş M3 renk sistemindeki yüzey ve yüzey varyantlarının yanı sıra yüzey, yüzey varyantı ve arka plan kullanma.

Örneğin, yüzey-varyant ile yüzey, farklı vurgu seviyeleri sağlamak için yüzeyde-varyant kullanılabilir.

Yüzey varyantları da aksanlı renklerden daha az vurgu sağlamak için vurgu renkleriyle de kullanılabilir. Ancak yine de erişilebilir olmak ve kontrast oranını korumak için kullanılır.

Yüzey, Arka Plan ve Yüzey varyantı renk rolleri.

Yüzey, arka plan ve yüzey varyantı renk rolleri.

  1. Metin için farklı yazı tipi ağırlıkları kullanma. Tipografi bölümünde gördüğünüz gibi farklı bir vurgu sağlamak için tür ölçeğinize özel ağırlıklar sağlayabilirsiniz.

Ardından, yüzey varyantını kullanarak vurgu farkını belirtmek için ReplyEmailListItem.kt güncellemesi yapın. 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 rengi onSurfaceVariant olarak güncellenecek. Bu, varsayılan olarak konu ve başlık metni composable'larına uygulanan onContainerColors ile karşılaştırıldığında sayfanın vurgusunu azaltır.

2c9b7f2bd016edb8.png 6850ff391f21e4ba.png

Zaman ve gövde metni, konu ve başlığa kıyasla aynı vurguya sahip (Sol).

Konu ve başlığa kıyasla daha az vurgulu zaman 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ı için tüm metin rengi varsayılan olarak onSecondaryContainer rengidir. Diğer e-postalarda arka plan surfaceVariant, olduğundan tüm metinlerin rengi varsayılan olarak onSurfaceVariant olur.

9. Tebrikler

Tebrikler! Bu codelab'i başarıyla tamamladınız. Uygulamanıza tema eklemek ve kişiselleştirilmiş bir deneyim sunmak için Compose ile Materyal temasını renk, yazı tipi ve şekillerin yanı sıra dinamik renkler kullanarak uyguladınız.

2d8fcabf15ac5202.png 5a4d31db0185dca6.png ce009e4ce560834d.png

Dinamik renkler ve renk teması uygulanmış tema oluşturma sonuçlarının sonu.

Sırada ne var?

Oluşturma yolu üzerindeki diğer codelab'lerimize göz atın:

Daha fazla bilgi

Örnek uygulamalar

Referans belgeler