Materyal Tasarım 2

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 Teması üzerine inşa edilmiştir. Malzeme Tasarımı, ürününüzün markasını daha iyi yansıtacak şekilde özelleştirmenin sistematik bir yoludur. Materyal Tema, renk, yazı ve şekil özelliklerini içerir. Bu özellikleri özelleştirdiğinizde, değişiklikleriniz uygulamanızı derlemek için kullandığınız bileşenlere otomatik olarak yansıtılır.

Jetpack Compose bu kavramları MaterialTheme composable ile uygular:

MaterialTheme(
    colors = // ...
    typography = // ...
    shapes = // ...
) {
    // app content
}

Uygulamanıza tema eklemek için MaterialTheme öğesine ilettiğiniz parametreleri yapılandırın.

Birbirine zıt iki ekran görüntüsü. İlk ekran, varsayılan MaterialTema stili,
ikinci ekran görüntüsünde değiştirilmiş stil kullanıyor.

Şekil 1. İlk ekran görüntüsünde MaterialTheme uygulamasını yapılandırmayan bir uygulama gösterildiği için bu uygulama varsayılan stili kullanıyor. İkinci ekran görüntüsünde, stili özelleştirmek için parametreleri MaterialTheme öğesine geçiren bir uygulama gösterilmektedir.

Renk

Renkler, Compose'da basit bir veri tutma sınıfı olan Color sınıfıyla modellenir.

val Red = Color(0xffff0000)
val Blue = Color(red = 0f, green = 0f, blue = 1f)

Bunları istediğiniz gibi düzenleyebilirsiniz (üst düzey sabit değerler, bir tekli veya tanımlı satır içi değer olarak), temanızda renkleri belirtmeniz ve renkleri oradan almanız kesinlikle önerilir. Bu yaklaşım, koyu tema ve iç içe yerleştirilmiş temaların kolayca desteklenmesini mümkün kılar.

Temanın renk paleti örneği

2. Şekil. Malzeme renk sistemi.

Compose, Malzeme renk sistemini modellemek için Colors sınıfını sağlar. Colors, açık veya koyu renklerden oluşan gruplar oluşturmak için oluşturucu işlevleri sağlar:

private val Yellow200 = Color(0xffffeb46)
private val Blue200 = Color(0xff91a4fc)
// ...

private val DarkColors = darkColors(
    primary = Yellow200,
    secondary = Blue200,
    // ...
)
private val LightColors = lightColors(
    primary = Yellow500,
    primaryVariant = Yellow400,
    secondary = Blue700,
    // ...
)

Colors tanımladıktan sonra bunları bir MaterialTheme öğesine iletebilirsiniz:

MaterialTheme(
    colors = if (darkTheme) DarkColors else LightColors
) {
    // app content
}

Tema renklerini kullanma

MaterialTheme composable'ına sağlanan Colors öğesini MaterialTheme.colors kullanarak alabilirsiniz.

Text(
    text = "Hello theming",
    color = MaterialTheme.colors.primary
)

Yüzey ve içerik rengi

Birçok bileşen bir çift rengi ve içerik rengini kabul eder:

Surface(
    color = MaterialTheme.colors.surface,
    contentColor = contentColorFor(color),
    // ...
) { /* ... */ }

TopAppBar(
    backgroundColor = MaterialTheme.colors.primarySurface,
    contentColor = contentColorFor(backgroundColor),
    // ...
) { /* ... */ }

Bu sayede yalnızca bir composable'ın rengini değil, aynı zamanda içindeki içerik için de varsayılan bir renk sağlayabilirsiniz. Birçok composable varsayılan olarak bu içerik rengini kullanır. Örneğin, Text, rengini üst öğesinin içerik rengine dayandırır ve Icon, tonunu ayarlamak için bu rengi kullanır.

Farklı renklere sahip aynı banner'dan iki örnek

3. Şekil. Farklı arka plan renkleri ayarlamak, farklı metin ve simge renkleri oluşturulmasına neden olur.

contentColorFor() yöntemi, tüm tema renkleri için uygun "on" rengini alır. Örneğin, Surface üzerinde bir primary arka plan rengi ayarlarsanız bu işlev, içerik rengi olarak onPrimary değerini ayarlamak için kullanılır. Tema olmayan bir arka plan rengi ayarlarsanız uygun bir içerik rengi de belirtmeniz gerekir. Hiyerarşide belirli bir konumda geçerli arka plan için tercih edilen içerik rengini almak amacıyla LocalContentColor özelliğini kullanın.

İçerik alfa

Genellikle, önem vermek ve görsel hiyerarşi sağlamak için içeriği ne kadar vurguladığınızı değiştirmek istersiniz. Materyal Tasarım'daki metinlerin okunabilirliği önerileri, farklı önem düzeylerini belirtmek için farklı opaklık seviyelerinin kullanılmasını önerir.

Jetpack Compose bunu LocalContentAlpha aracılığıyla uygular. Bu CompositionLocal için bir değer sağlayarak bir hiyerarşi için içerik alfası belirtebilirsiniz. İç içe yerleştirilmiş composable'lar, alfa işlemini içeriklerine uygulamak için bu değeri kullanabilir. Örneğin Text ve Icon varsayılan olarak LocalContentAlpha kullanılacak şekilde ayarlanmış LocalContentColor kombinasyonunu kullanır. Materyal, ContentAlpha nesnesi tarafından modellenen bazı standart alfa değerleri (high, medium, disabled) belirtiyor.

// By default, both Icon & Text use the combination of LocalContentColor &
// LocalContentAlpha. De-emphasize content by setting content alpha
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
    Text(
        // ...
    )
}
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.disabled) {
    Icon(
        // ...
    )
    Text(
        // ...
    )
}

CompositionLocal hakkında daha fazla bilgi edinmek için CompositionLocal ile yerel kapsamlı veriler'i inceleyin.

Makale başlığının farklı düzeylerde metin vurgulamasını gösteren ekran görüntüsü

4. Şekil. Bilgi hiyerarşisini görsel olarak iletmek için metne farklı vurgu düzeyleri uygulayın. Metnin ilk satırı başlık olduğundan ve en önemli bilgileri içerdiğinden ContentAlpha.high ifadesini kullanır. İkinci satır daha az önemli meta veriler içerdiği için ContentAlpha.medium değerini kullanır.

Koyu tema

Compose'da MaterialTheme composable'ına farklı Colors grupları sağlayarak açık ve koyu temaları uygularsınız:

@Composable
fun MyTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {
    MaterialTheme(
        colors = if (darkTheme) DarkColors else LightColors,
        /*...*/
        content = content
    )
}

Bu örnekte MaterialTheme, koyu tema kullanılıp kullanılmayacağını belirten bir parametreyi kabul eden kendi composable işlevi içinde sarmalanmıştır. Bu durumda işlev, cihaz teması ayarını sorgulayarak darkTheme için varsayılan değeri alır.

Mevcut Colors değerinin açık mı yoksa koyu mu olduğunu kontrol etmek için aşağıdaki gibi bir kod kullanabilirsiniz:

val isLightTheme = MaterialTheme.colors.isLight
Icon(
    painterResource(
        id = if (isLightTheme) {
            R.drawable.ic_sun_24
        } else {
            R.drawable.ic_moon_24
        }
    ),
    contentDescription = "Theme"
)

Yükseklik yer paylaşımları

Materyal uygulamasında, daha yüksek yükseltilere sahip koyu temalardaki yüzeyler, arka planlarını aydınlatan yükseklik yer paylaşımları alır. Bir yüzeyin rakımı ne kadar yüksek olursa (ima edilen ışık kaynağına yaklaştırıldığında) yüzey o kadar açık olur.

Bu bindirmeler, koyu renkler kullanılırken Surface composable'ı ve yüzey kullanan diğer Material composable'ları tarafından otomatik olarak uygulanır:

Surface(
    elevation = 2.dp,
    color = MaterialTheme.colors.surface, // color will be adjusted for elevation
    /*...*/
) { /*...*/ }

Farklı yükseklik seviyelerindeki öğeler için kullanılan biraz farklı renkleri gösteren bir uygulama ekran görüntüsü

5. Şekil. Hem kartlarda hem de alt gezinme kartlarında arka plan olarak surface rengi kullanılıyor. Kartlar ve alt gezinme bölümleri, arka planın üzerinde farklı yükseklik düzeylerinde yer aldığından biraz farklı renklere sahiptir: Kartlar arka plandan daha açık, alt gezinme bölümü ise kartlardan daha açık renklidir.

Surface içermeyen özel senaryolar için LocalElevationOverlay, yani Surface bileşenleri tarafından kullanılan ElevationOverlay öğesini içeren CompositionLocal kullanın:

// Elevation overlays
// Implemented in Surface (and any components that use it)
val color = MaterialTheme.colors.surface
val elevation = 4.dp
val overlaidColor = LocalElevationOverlay.current?.apply(
    color, elevation
)

Yükseklik yer paylaşımlarını devre dışı bırakmak için, oluşturulabilir bir hiyerarşide istediğiniz noktada null sağlayın:

MyTheme {
    CompositionLocalProvider(LocalElevationOverlay provides null) {
        // Content without elevation overlays
    }
}

Sınırlı renk vurguları

Malzeme, çoğu durumda primary rengi yerine surface renginin kullanılmasını tercih ederek koyu temalar için sınırlı renk vurguları uygulanmasını önerir. TopAppBar ve BottomNavigation gibi malzeme composable'ları bu davranışı varsayılan olarak uygular.

6. Şekil. sınırlı renk vurgularına sahip koyu renkli malzeme teması. Üst uygulama çubuğu açık temada birincil rengi, koyu temada yüzey rengi kullanır.

Özel senaryolar için primarySurface uzantı özelliğini kullanın:

Surface(
    // Switches between primary in light theme and surface in dark theme
    color = MaterialTheme.colors.primarySurface,
    /*...*/
) { /*...*/ }

Yazı biçimi

Materyal, bir tür sistemi tanımlayarak sizi anlamsal olarak adlandırılmış az sayıda stil kullanmaya teşvik eder.

Çeşitli stillerde birkaç farklı yazı biçimi örneği

7. Şekil. Malzeme türü sistemi.

Compose, tür sistemini Typography, TextStyle ve yazı tipiyle ilgili sınıflarıyla uygular. Typography oluşturucu, özelleştirmek istemediğiniz stilleri çıkarabilirsiniz. Böylece her stil için varsayılanlar sunulur:

val raleway = FontFamily(
    Font(R.font.raleway_regular),
    Font(R.font.raleway_medium, FontWeight.W500),
    Font(R.font.raleway_semibold, FontWeight.SemiBold)
)

val myTypography = Typography(
    h1 = TextStyle(
        fontFamily = raleway,
        fontWeight = FontWeight.W300,
        fontSize = 96.sp
    ),
    body1 = TextStyle(
        fontFamily = raleway,
        fontWeight = FontWeight.W600,
        fontSize = 16.sp
    )
    /*...*/
)
MaterialTheme(typography = myTypography, /*...*/) {
    /*...*/
}

Genel olarak aynı yazı tipini kullanmak istiyorsanız defaultFontFamily parameter öğesini belirtin ve TextStyle öğelerinin fontFamily kısmını çıkarın:

val typography = Typography(defaultFontFamily = raleway)
MaterialTheme(typography = typography, /*...*/) {
    /*...*/
}

Metin stillerini kullanma

TextStyle öğelerine MaterialTheme.typography üzerinden erişilebilir. TextStyle öğelerini şu şekilde alın:

Text(
    text = "Subtitle2 styled",
    style = MaterialTheme.typography.subtitle2
)

Farklı amaçlar için farklı yazı tiplerinin karışımını gösteren ekran görüntüsü

8. Şekil. Markanızı ifade etmek için çeşitli yazı tipleri ve stiller kullanın.

Şekil

Malzeme bir şekil sistemi tanımlayarak büyük, orta ve küçük bileşenler için şekiller tanımlamanızı sağlar.

Çeşitli Materyal Tasarım şekillerini gösterir

9. Şekil. Malzeme şekil sistemi.

Compose, şekil sistemini Shapes sınıfıyla uygular ve böylece her boyut kategorisi için bir CornerBasedShape belirtmenizi sağlar:

val shapes = Shapes(
    small = RoundedCornerShape(percent = 50),
    medium = RoundedCornerShape(0f),
    large = CutCornerShape(
        topStart = 16.dp,
        topEnd = 0.dp,
        bottomEnd = 0.dp,
        bottomStart = 16.dp
    )
)

MaterialTheme(shapes = shapes, /*...*/) {
    /*...*/
}

Birçok bileşen bu şekilleri varsayılan olarak kullanır. Örneğin Button, TextField ve FloatingActionButton varsayılan olarak küçük, AlertDialog varsayılan olarak orta, ModalDrawer varsayılan olarak büyük boyuttur. Eşlemenin tamamı için şekil şeması referansına bakın.

Şekilleri kullanma

Shape öğelerine MaterialTheme.shapes üzerinden erişilebilir. Shape öğelerini aşağıdaki gibi bir kodla alın:

Surface(
    shape = MaterialTheme.shapes.medium, /*...*/
) {
    /*...*/
}

Bir öğenin hangi durumda olduğunu aktarmak için Malzeme şekilleri kullanan bir uygulamanın ekran görüntüsü

Şekil 10. Markayı veya durumu ifade etmek için şekiller kullanın.

Varsayılan stiller

Android Görünümleri'ndeki varsayılan stillerden Oluşturma işlevinde eşdeğer bir kavram yoktur. Materyal bileşenlerini saran kendi "aşırı yük" composable işlevlerinizi oluşturarak benzer işlevleri sağlayabilirsiniz. Örneğin, bir düğme stili oluşturmak için kendi composable işlevinizde bir düğmeyi sarmalayın, değiştirmek istediğiniz parametreleri doğrudan ayarlayın ve diğerlerini parametre olarak içeren composable'ın gösterin.

@Composable
fun MyButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    content: @Composable RowScope.() -> Unit
) {
    Button(
        colors = ButtonDefaults.buttonColors(
            backgroundColor = MaterialTheme.colors.secondary
        ),
        onClick = onClick,
        modifier = modifier,
        content = content
    )
}

Tema yer paylaşımları

MaterialTheme composable'ları iç içe yerleştirerek, Compose'da Android Görünümleri'ndeki tema yer paylaşımlarına eşdeğer bir deneyim elde edebilirsiniz. MaterialTheme renk, yazı tipi ve şekilleri varsayılan olarak geçerli tema değerine ayarlar. Bu nedenle, bir tema bu parametrelerden yalnızca birini ayarlarsa diğer parametreler varsayılan değerlerini korur.

Ayrıca, Görünüme dayalı ekranları Oluşturma'ya taşırken android:theme özelliğinin kullanımına dikkat edin. Oluşturma kullanıcı arayüzü ağacının ilgili bölümünde yeni bir MaterialTheme eklemeniz gerekebilir.

Baykuş örneğinde, ayrıntılar ekranında ekranın büyük kısmı için bir PinkTheme ve ilgili bölüm için bir BlueTheme kullanılır. Aşağıdaki ekran görüntüsüne ve koda bakın.

Şekil 11. Baykuş örneğinde iç içe yerleştirilmiş temalar.

@Composable
fun DetailsScreen(/* ... */) {
    PinkTheme {
        // other content
        RelatedSection()
    }
}

@Composable
fun RelatedSection(/* ... */) {
    BlueTheme {
        // content
    }
}

Bileşen durumları

Etkileşimde bulunulabilen (tıklanan, açılıp açılabilen vb.) malzeme bileşenleri farklı görsel durumlarda olabilir. Durumlar şunlardır: etkin, devre dışı, basıldı vb.

Composable'lar genellikle enabled parametresine sahiptir. false olarak ayarlamak etkileşimi engeller ve bileşen durumunu görsel olarak iletmek için renk ve yükseklik gibi özellikleri değiştirir.

Şekil 12. enabled = true (sol) ve enabled = false (sağ) içeren düğme.

Çoğu durumda renk ve yükseklik gibi değerler için varsayılan değerleri kullanabilirsiniz. Farklı durumlarda kullanılan değerleri yapılandırmak isterseniz kullanabileceğiniz sınıflar ve kolaylık işlevleri bulunur. Aşağıdaki düğme örneğine bakın:

Button(
    onClick = { /* ... */ },
    enabled = true,
    // Custom colors for different states
    colors = ButtonDefaults.buttonColors(
        backgroundColor = MaterialTheme.colors.secondary,
        disabledBackgroundColor = MaterialTheme.colors.onBackground
            .copy(alpha = 0.2f)
            .compositeOver(MaterialTheme.colors.background)
        // Also contentColor and disabledContentColor
    ),
    // Custom elevation for different states
    elevation = ButtonDefaults.elevation(
        defaultElevation = 8.dp,
        disabledElevation = 2.dp,
        // Also pressedElevation
    )
) { /* ... */ }

Şekil 13. Ayarlanmış renk ve yükseklik değerlerine sahip, enabled = true (sol) ve enabled = false (sağ) düğmeleri olan düğme.

Küçük Dalgalar

Malzeme bileşenleri, etkileşimde bulunduklarını belirtmek için dalgaları kullanır. Hiyerarşinizde MaterialTheme kullanıyorsanız clickable ve indication gibi iç değiştiriciler içinde varsayılan olarak Indication Ripple kullanılır.

Çoğu durumda varsayılan Ripple kullanılabilir. Görünümlerini yapılandırmak isterseniz renk ve alfa gibi özellikleri değiştirmek için RippleTheme aracını kullanabilirsiniz.

RippleTheme hizmetinin kapsamını genişleterek defaultRippleColor ve defaultRippleAlpha yardımcı işlevlerinden yararlanabilirsiniz. Daha sonra LocalRippleTheme kullanarak hiyerarşinizde özel dalga temanızı sağlayabilirsiniz:

@Composable
fun MyApp() {
    MaterialTheme {
        CompositionLocalProvider(
            LocalRippleTheme provides SecondaryRippleTheme
        ) {
            // App content
        }
    }
}

@Immutable
private object SecondaryRippleTheme : RippleTheme {
    @Composable
    override fun defaultColor() = RippleTheme.defaultRippleColor(
        contentColor = MaterialTheme.colors.secondary,
        lightTheme = MaterialTheme.colors.isLight
    )

    @Composable
    override fun rippleAlpha() = RippleTheme.defaultRippleAlpha(
        contentColor = MaterialTheme.colors.secondary,
        lightTheme = MaterialTheme.colors.isLight
    )
}

alternatif metin

Şekil 14. RippleTheme aracılığıyla sağlanan, farklı dalga değerlerine sahip düğmeler.

Daha fazla bilgi

Oluşturma'da Materyal Temaları hakkında daha fazla bilgi edinmek için aşağıdaki ek kaynaklara bakın.

Codelab uygulamaları

Videolar