Oluşturma modunda gölge ekleme

Gölgeler, kullanıcı arayüzünüzü görsel olarak iyileştirir, kullanıcılara etkileşimi gösterir ve kullanıcı işlemlerine ilişkin anında geri bildirim sağlar. Compose, uygulamanıza gölge eklemenin çeşitli yollarını sunar:

  • Modifier.shadow(): Materyal Tasarım yönergelerine uygun bir composable'ın arkasında yüksekliğe dayalı bir gölge oluşturur.
  • Modifier.dropShadow(): Bir composable'ın arkasında görünen ve composable'ı yükseltilmiş gibi gösteren özelleştirilebilir bir gölge oluşturur.
  • Modifier.innerShadow(): Bir composable'ın kenarlıkları içinde gölge oluşturarak composable'ın arkasındaki yüzeye bastırılmış gibi görünmesini sağlar.

Modifier.shadow() temel gölgeler oluşturmak için uygundur. dropShadow ve innerShadow değiştiricileri ise gölge oluşturma üzerinde daha ayrıntılı kontrol ve hassasiyet sağlar.

Bu sayfada, kullanıcı etkileşimi üzerine gölgeleri animasyonla gösterme ve innerShadow() ile dropShadow() değiştiricilerini zincirleyerek değişen gölgeler, neomorfik gölgeler ve daha fazlasını oluşturma dahil olmak üzere bu değiştiricilerin her birinin nasıl uygulanacağı açıklanmaktadır.

Temel gölgeler oluşturma

Modifier.shadow(), yukarıdan gelen bir ışık kaynağını simüle eden Material Design yönergelerine uygun temel bir gölge oluşturur. Gölge derinliği, elevation değerine dayanır ve yayınlanan gölge, composable'ın şekliyle kırpılır.

@Composable
fun ElevationBasedShadow() {
    Box(
        modifier = Modifier.aspectRatio(1f).fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        Box(
            Modifier
                .size(100.dp, 100.dp)
                .shadow(10.dp, RectangleShape)
                .background(Color.White)
        )
    }
}

Beyaz dikdörtgen şeklin etrafında oluşan gri gölge.
1. şekil. Modifier.shadow ile oluşturulmuş, yüksekliğe dayalı bir gölge.

Gölge uygulama

İçeriğinizin arkasına doğru bir gölge çizmek için dropShadow() değiştiricisini kullanın. Bu, öğenin yükseltilmiş gibi görünmesini sağlar.

Aşağıdaki temel özellikleri Shadow parametresi aracılığıyla kontrol edebilirsiniz:

  • radius: Bulanıklığınızın yumuşaklığını ve dağılımını tanımlar.
  • color: Tonlamanın rengini tanımlar.
  • offset: Gölgenin geometrisini x ve y eksenleri boyunca konumlandırır.
  • spread: Gölgenin geometrisinin genişlemesini veya daralmasını kontrol eder.

Ayrıca, shape parametresi gölgenin genel şeklini tanımlar. androidx.compose.foundation.shape paketindeki tüm geometrileri ve Material Expressive şekillerini kullanabilir.

Temel bir gölge uygulamak için dropShadow() değiştiricisini composable zincirinize ekleyerek yarıçapı, rengi ve yayılımı belirtin. Gölgenin üzerinde görünen purpleColor arka planının, purpleColor değiştiricisinden sonra çizildiğini unutmayın:dropShadow()

@Composable
fun SimpleDropShadowUsage() {
    Box(Modifier.fillMaxSize()) {
        Box(
            Modifier
                .width(300.dp)
                .height(300.dp)
                .dropShadow(
                    shape = RoundedCornerShape(20.dp),
                    shadow = Shadow(
                        radius = 10.dp,
                        spread = 6.dp,
                        color = Color(0x40000000),
                        offset = DpOffset(x = 4.dp, 4.dp)
                    )
                )
                .align(Alignment.Center)
                .background(
                    color = Color.White,
                    shape = RoundedCornerShape(20.dp)
                )
        ) {
            Text(
                "Drop Shadow",
                modifier = Modifier.align(Alignment.Center),
                fontSize = 32.sp
            )
        }
    }
}

Kodla ilgili önemli noktalar

  • dropShadow() değiştiricisi, içteki Box için uygulanır. Gölge aşağıdaki özelliklere sahiptir:
    • Yuvarlak dikdörtgen şekli (RoundedCornerShape(20.dp))
    • Kenarları yumuşak ve dağınık hale getiren 10.dp bulanıklık yarıçapı
    • Gölgenin boyutunu genişleten ve onu, gölgeyi oluşturan kutudan daha büyük hale getiren 6.dp yayılımı
    • Gölgeyi yarı şeffaf hale getiren 0.5f alfa değeri
  • Gölge tanımlandıktan sonra .background() değiştiricisi uygulanır.
    • Box beyaz renkle doldurulur.
    • Arka plan, gölgeyle aynı yuvarlak dikdörtgen şekline kırpılır.

Sonuç

Beyaz dikdörtgen şeklin etrafına düşen gri gölge.
Şekil 2. Şeklin etrafına çizilen gölge.

İç gölgeler uygulama

dropShadow öğesinin tersi bir efekt oluşturmak için Modifier.innerShadow() öğesini kullanın. Bu öğe, bir öğenin alttaki yüzeye gömülmüş veya bastırılmış olduğu yanılsamasını yaratır.

İç gölgeler oluştururken sıra önemlidir. İç gölge, içeriğin üstüne çizilir. Bu nedenle, genellikle şunları yapmanız gerekir:

  1. Arka plan içeriğinizi çizin.
  2. İçbükey görünüm oluşturmak için innerShadow() değiştiricisini uygulayın.

innerShadow() simgesi arka plandan önce yerleştirilirse arka plan, gölgenin üzerine çizilerek gölgeyi tamamen gizler.

Aşağıdaki örnekte, innerShadow() öğesinin RoundedCornerShape üzerinde uygulanması gösterilmektedir:

@Composable
fun SimpleInnerShadowUsage() {
    Box(Modifier.fillMaxSize()) {
        Box(
            Modifier
                .width(300.dp)
                .height(200.dp)
                .align(Alignment.Center)
                // note that the background needs to be defined before defining the inner shadow
                .background(
                    color = Color.White,
                    shape = RoundedCornerShape(20.dp)
                )
                .innerShadow(
                    shape = RoundedCornerShape(20.dp),
                    shadow = Shadow(
                        radius = 10.dp,
                        spread = 2.dp,
                        color = Color(0x40000000),
                        offset = DpOffset(x = 6.dp, 7.dp)
                    )
                )

        ) {
            Text(
                "Inner Shadow",
                modifier = Modifier.align(Alignment.Center),
                fontSize = 32.sp
            )
        }
    }
}

Beyaz dikdörtgen şeklinin içinde gri bir iç gölge.
3.şekil Yuvarlatılmış köşeli bir dikdörtgen üzerinde Modifier.innerShadow() uygulaması.

Kullanıcı etkileşiminde gölgeleri canlandır

Gölgelerinizin kullanıcı etkileşimlerine yanıt vermesini sağlamak için gölge özelliklerini Compose'un animasyon API'leriyle entegre edebilirsiniz. Kullanıcı bir düğmeye bastığında, örneğin gölge anında görsel geri bildirim sağlamak için değişebilir.

Aşağıdaki kod, gölgeyle birlikte "basılmış" efekti oluşturur (yüzeyin ekrana doğru itildiği yanılsaması):

@Composable
fun AnimatedColoredShadows() {
    SnippetsTheme {
        Box(Modifier.fillMaxSize()) {
            val interactionSource = remember { MutableInteractionSource() }
            val isPressed by interactionSource.collectIsPressedAsState()

            // Create transition with pressed state
            val transition = updateTransition(
                targetState = isPressed,
                label = "button_press_transition"
            )

            fun <T> buttonPressAnimation() = tween<T>(
                durationMillis = 400,
                easing = EaseInOut
            )

            // Animate all properties using the transition
            val shadowAlpha by transition.animateFloat(
                label = "shadow_alpha",
                transitionSpec = { buttonPressAnimation() }
            ) { pressed ->
                if (pressed) 0f else 1f
            }
            // ...

            val blueDropShadow by transition.animateColor(
                label = "shadow_color",
                transitionSpec = { buttonPressAnimation() }
            ) { pressed ->
                if (pressed) Color.Transparent else blueDropShadowColor
            }

            // ...

            Box(
                Modifier
                    .clickable(
                        interactionSource, indication = null
                    ) {
                        // ** ...... **//
                    }
                    .width(300.dp)
                    .height(200.dp)
                    .align(Alignment.Center)
                    .dropShadow(
                        shape = RoundedCornerShape(70.dp),
                        shadow = Shadow(
                            radius = 10.dp,
                            spread = 0.dp,
                            color = blueDropShadow,
                            offset = DpOffset(x = 0.dp, -(2).dp),
                            alpha = shadowAlpha
                        )
                    )
                    .dropShadow(
                        shape = RoundedCornerShape(70.dp),
                        shadow = Shadow(
                            radius = 10.dp,
                            spread = 0.dp,
                            color = darkBlueDropShadow,
                            offset = DpOffset(x = 2.dp, 6.dp),
                            alpha = shadowAlpha
                        )
                    )
                    // note that the background needs to be defined before defining the inner shadow
                    .background(
                        color = Color(0xFFFFFFFF),
                        shape = RoundedCornerShape(70.dp)
                    )
                    .innerShadow(
                        shape = RoundedCornerShape(70.dp),
                        shadow = Shadow(
                            radius = 8.dp,
                            spread = 4.dp,
                            color = innerShadowColor2,
                            offset = DpOffset(x = 4.dp, 0.dp)
                        )
                    )
                    .innerShadow(
                        shape = RoundedCornerShape(70.dp),
                        shadow = Shadow(
                            radius = 20.dp,
                            spread = 4.dp,
                            color = innerShadowColor1,
                            offset = DpOffset(x = 4.dp, 0.dp),
                            alpha = innerShadowAlpha
                        )
                    )

            ) {
                Text(
                    "Animated Shadows",
                    // ...
                )
            }
        }
    }
}

Kodla ilgili önemli noktalar

  • transition.animateColor ve transition.animateFloat ile basıldığında animasyon uygulanacak parametrelerin başlangıç ve bitiş durumlarını bildirir.
  • updateTransition kullanır ve tüm animasyonların senkronize edildiğini doğrulamak için seçilen targetState (targetState = isPressed) ile birlikte sağlar. isPressed her değiştiğinde, geçiş nesnesi tüm alt özelliklerin animasyonunu mevcut değerlerinden yeni hedef değerlere otomatik olarak yönetir.
  • Geçişin zamanlamasını ve yumuşaklığını kontrol eden buttonPressAnimation spesifikasyonunu tanımlar. 400 milisaniye süreli ve EaseInOut eğrili bir tween (arada anlamına gelir) belirtir. Bu, animasyonun yavaş başlayıp ortada hızlanacağı ve sonunda yavaşlayacağı anlamına gelir.
  • Aşağıdakiler de dahil olmak üzere, tüm animasyonlu özellikleri uygulayarak görsel öğeyi oluşturan bir değiştirici işlevler zinciriyle Box tanımlar:
    • .clickable(): Box öğesini etkileşimli hale getiren bir değiştiricidir.
    • .dropShadow(): Önce iki dış gölge uygulanır. Renk ve alfa özellikleri, animasyonlu değerlere (blueDropShadow vb.) bağlıdır ve ilk yükseltilmiş görünümü oluşturur.
    • .innerShadow(): Arka planın üzerine iki iç gölge çizilir. Bu özellikler, diğer animasyonlu değerler grubuyla (innerShadowColor1 vb.) bağlantılıdır ve girintili görünümü oluşturur.

Sonuç

Şekil 4. Kullanıcı bastığında animasyonlu bir gölge.

Renk geçişli gölgeler oluşturma

Gölgeler düz renklerle sınırlı değildir. Shadow API, Brush kabul eder. Bu sayede gradyan gölgeler oluşturabilirsiniz.

Box(
    modifier = Modifier
        .width(240.dp)
        .height(200.dp)
        .dropShadow(
            shape = RoundedCornerShape(70.dp),
            shadow = Shadow(
                radius = 10.dp,
                spread = animatedSpread.dp,
                brush = Brush.sweepGradient(
                    colors
                ),
                offset = DpOffset(x = 0.dp, y = 0.dp),
                alpha = animatedAlpha
            )
        )
        .clip(RoundedCornerShape(70.dp))
        .background(Color(0xEDFFFFFF)),
    contentAlignment = Alignment.Center
) {
    Text(
        text = breathingText,
        color = Color.Black,
        style = MaterialTheme.typography.bodyLarge
    )
}

Kodla ilgili önemli noktalar

  • dropShadow() kutunun arkasına gölge ekler.
  • brush = Brush.sweepGradient(colors), gölgeyi önceden tanımlanmış colors listesinde dönen bir gradyanla renklendirerek gökkuşağı benzeri bir efekt oluşturur.

Sonuç

"Nefes alan" bir animasyonla dropShadow() degrade oluşturmak için fırçayı gölge olarak kullanabilirsiniz:

Şekil 5. Animasyonlu gradyan gölge.

Gölgeleri birleştirme

Çeşitli efektler oluşturmak için dropShadow() ve innerShadow() değiştiricilerini birleştirip katmanlayabilirsiniz. Aşağıdaki bölümlerde, bu teknikle nasıl neomorfik, neobrutalist ve gerçekçi gölgeler oluşturacağınız gösterilmektedir.

Neumorfik gölgeler oluşturma

Neumorfik gölgeler, arka plandan doğal olarak ortaya çıkan yumuşak bir görünüme sahiptir. Neumorfik gölgeler oluşturmak için aşağıdakileri yapın:

  1. Arka planıyla aynı renklere sahip bir öğe kullanın.
  2. İki soluk, zıt gölge uygulayın: Bir köşeye açık, diğer köşeye koyu gölge.

Aşağıdaki snippet, dropShadow() değiştiricilerini katmanlayarak neomorfik efekti oluşturur:

@Composable
fun NeumorphicRaisedButton(
    shape: RoundedCornerShape = RoundedCornerShape(30.dp)
) {
    val bgColor = Color(0xFFe0e0e0)
    val lightShadow = Color(0xFFFFFFFF)
    val darkShadow = Color(0xFFb1b1b1)
    val upperOffset = -10.dp
    val lowerOffset = 10.dp
    val radius = 15.dp
    val spread = 0.dp
    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(bgColor)
            .wrapContentSize(Alignment.Center)
            .size(240.dp)
            .dropShadow(
                shape,
                shadow = Shadow(
                    radius = radius,
                    color = lightShadow,
                    spread = spread,
                    offset = DpOffset(upperOffset, upperOffset)
                ),
            )
            .dropShadow(
                shape,
                shadow = Shadow(
                    radius = radius,
                    color = darkShadow,
                    spread = spread,
                    offset = DpOffset(lowerOffset, lowerOffset)
                ),

            )
            .background(bgColor, shape)
    )
}

Beyaz arka plan üzerinde, neomorfik efektli beyaz dikdörtgen şekil.
6.şekil Neumorfik gölge efekti.

Yeni brutalist gölgeler oluşturma

Neobrutalist stil, yüksek kontrastlı, bloklu düzenleri, canlı renkleri ve kalın kenarlıkları öne çıkarır. Bu efekti oluşturmak için aşağıdaki snippet'te gösterildiği gibi, bulanıklığı sıfır olan ve belirgin bir ofsete sahip bir dropShadow() kullanın:

@Composable
fun NeoBrutalShadows() {
    SnippetsTheme {
        val dropShadowColor = Color(0xFF007AFF)
        val borderColor = Color(0xFFFF2D55)
        Box(Modifier.fillMaxSize()) {
            Box(
                Modifier
                    .width(300.dp)
                    .height(200.dp)
                    .align(Alignment.Center)
                    .dropShadow(
                        shape = RoundedCornerShape(0.dp),
                        shadow = Shadow(
                            radius = 0.dp,
                            spread = 0.dp,
                            color = dropShadowColor,
                            offset = DpOffset(x = 8.dp, 8.dp)
                        )
                    )
                    .border(
                        8.dp, borderColor
                    )
                    .background(
                        color = Color.White,
                        shape = RoundedCornerShape(0.dp)
                    )
            ) {
                Text(
                    "Neobrutal Shadows",
                    modifier = Modifier.align(Alignment.Center),
                    style = MaterialTheme.typography.bodyMedium
                )
            }
        }
    }
}

Sarı arka plan üzerinde, mavi gölgeli beyaz bir dikdörtgenin etrafında kırmızı bir kenarlık var.
7.şekil Neobrutalist bir gölge efekti.

Gerçekçi gölgeler oluşturma

Gerçekçi gölgeler, fiziksel dünyadaki gölgeleri taklit eder. Birincil ışık kaynağıyla aydınlatılmış gibi görünürler. Bu da hem doğrudan gölge hem de daha dağınık bir gölge oluşturur. Aşağıdaki snippet'te gösterildiği gibi, gerçekçi gölge efektleri oluşturmak için farklı özelliklere sahip birden fazla dropShadow() ve innerShadow() örneğini üst üste yerleştirebilirsiniz:

@Composable
fun RealisticShadows() {
    Box(Modifier.fillMaxSize()) {
        val dropShadowColor1 = Color(0xB3000000)
        val dropShadowColor2 = Color(0x66000000)

        val innerShadowColor1 = Color(0xCC000000)
        val innerShadowColor2 = Color(0xFF050505)
        val innerShadowColor3 = Color(0x40FFFFFF)
        val innerShadowColor4 = Color(0x1A050505)
        Box(
            Modifier
                .width(300.dp)
                .height(200.dp)
                .align(Alignment.Center)
                .dropShadow(
                    shape = RoundedCornerShape(100.dp),
                    shadow = Shadow(
                        radius = 40.dp,
                        spread = 0.dp,
                        color = dropShadowColor1,
                        offset = DpOffset(x = 2.dp, 8.dp)
                    )
                )
                .dropShadow(
                    shape = RoundedCornerShape(100.dp),
                    shadow = Shadow(
                        radius = 4.dp,
                        spread = 0.dp,
                        color = dropShadowColor2,
                        offset = DpOffset(x = 0.dp, 4.dp)
                    )
                )
                // note that the background needs to be defined before defining the inner shadow
                .background(
                    color = Color.Black,
                    shape = RoundedCornerShape(100.dp)
                )
// //
                .innerShadow(
                    shape = RoundedCornerShape(100.dp),
                    shadow = Shadow(
                        radius = 12.dp,
                        spread = 3.dp,
                        color = innerShadowColor1,
                        offset = DpOffset(x = 6.dp, 6.dp)
                    )
                )
                .innerShadow(
                    shape = RoundedCornerShape(100.dp),
                    shadow = Shadow(
                        radius = 4.dp,
                        spread = 1.dp,
                        color = Color.White,
                        offset = DpOffset(x = 5.dp, 5.dp)
                    )
                )
                .innerShadow(
                    shape = RoundedCornerShape(100.dp),
                    shadow = Shadow(
                        radius = 12.dp,
                        spread = 5.dp,
                        color = innerShadowColor2,
                        offset = DpOffset(x = (-3).dp, (-12).dp)
                    )
                )
                .innerShadow(
                    shape = RoundedCornerShape(100.dp),
                    shadow = Shadow(
                        radius = 3.dp,
                        spread = 10.dp,
                        color = innerShadowColor3,
                        offset = DpOffset(x = 0.dp, 0.dp)
                    )
                )
                .innerShadow(
                    shape = RoundedCornerShape(100.dp),
                    shadow = Shadow(
                        radius = 3.dp,
                        spread = 9.dp,
                        color = innerShadowColor4,
                        offset = DpOffset(x = 1.dp, 1.dp)
                    )
                )

        ) {
            Text(
                "Realistic Shadows",
                modifier = Modifier.align(Alignment.Center),
                fontSize = 24.sp,
                color = Color.White
            )
        }
    }
}

Kodla ilgili önemli noktalar

  • Farklı özelliklere sahip iki zincirli dropShadow() değiştirici uygulanır, ardından bir background değiştirici uygulanır.
  • Zincirleme innerShadow() değiştiriciler, bileşenin kenarında metalik çerçeve efekti oluşturmak için uygulanır.

Sonuç

Önceki kod snippet'i aşağıdakileri üretir:

Siyah yuvarlak şeklin etrafında beyaz gerçekçi bir gölge.
Şekil 8. Gerçekçi bir gölge efekti.