Bulanıklaştırmanın yaygın kullanım alanları

Aşağıdaki bölümlerde, yaygın kullanıcı arayüzü kalıpları için Modifier.blur, BlurRadiusSpec, BlurStop ve BlurScope'un nasıl birleştirileceği gösterilmektedir. Bu API'lere giriş için Compose'da bulanıklaştırma başlıklı makaleyi inceleyin.

Kaydırılabilir veya sürüklenebilir içeriğin kenarlarını bulanıklaştırma

Kayan bir liste, bant veya seçici gösterirken, etkin merkez bölgeyi keskin bir şekilde odakta tutarken kapsayıcı kenarlarına yakın öğeleri yumuşatmak için çok adımlı aşamalı bulanıklaştırmalar kullanabilirsiniz.

Kaydırılabilir bir listenin üst ve alt kenarlarını soldurma

Öğeler dikey bir listenin görüntü alanına girip çıkarken geçişleri yumuşatmak için LazyColumn öğesine BlurStop girişleri olan BlurRadiusSpec.verticalGradient uygulayın. Şarkı sözlerini satır satır kaydıran aşağıdaki örnekte, 0.dp durakları 0.42f ve 0.58f arasında etkin satırı merkezde net tutarken üst ve alt kenarlara doğru olan satırlar kademeli olarak bulanıklaşır:

@Composable
fun SongListTopBottomBlurExample(lyrics: List<String>) {
    // ...
    LazyColumn(
        state = listState,
        flingBehavior = flingBehavior,
        modifier = Modifier
            .width(330.dp)
            .height(480.dp)
            .padding(horizontal = 24.dp)
            .blur(
                blurRadiusSpec = BlurRadiusSpec.verticalGradient(
                    stops = listOf(
                        BlurStop(fraction = 0.00f, radius = 18.dp), // Heavily blurred top edge
                        BlurStop(fraction = 0.24f, radius = 8.dp), // Soft upper transition
                        BlurStop(fraction = 0.42f, radius = 0.dp), // Sharp center focus starts
                        BlurStop(fraction = 0.58f, radius = 0.dp), // Sharp center focus ends
                        BlurStop(fraction = 0.76f, radius = 8.dp), // Soft lower transition
                        BlurStop(fraction = 1.00f, radius = 18.dp), // Heavily blurred bottom edge
                    ),
                ),
                edgeTreatment = BlurredEdgeTreatment.Unbounded,
            ),
        contentPadding = PaddingValues(vertical = 36.dp),
        verticalArrangement = Arrangement.spacedBy(26.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
    ) {
        // ...
    }
}

Şekil 1. Şarkı sözü satırlarının dikey bir listesi. Üst ve alt satırlar bulanıklaşarak kaybolurken ortadaki satır net bir şekilde görünüyor.

Yatay bir kontrolün sol ve sağ kenarlarını soldurma

Benzer şekilde, tekerlek seçici, bant veya ölçüm ölçeği gibi yatay olarak kaydırılabilir ya da sürüklenebilir bir bileşenin ortasına odaklanmak için BlurStop girişleriyle BlurRadiusSpec.horizontalGradient uygulayın. Aşağıdaki sürüklenebilir ağırlık ölçeğinde, sol ve sağ kenarlar yumuşatılırken merkez gösterge iğnesinin yanındaki işaretler ve sayılar tamamen keskin kalır:

@Composable
fun HorizontalScaleBlurExample() {
    var selectedValue by remember { mutableFloatStateOf(65.0f) }
    val animatedValue by animateFloatAsState(
        targetValue = selectedValue,
        animationSpec = tween(durationMillis = 900, easing = FastOutSlowInEasing),
        label = "horizontalScaleSmoothScroll",
    )
    Column(
        modifier = Modifier
            .width(340.dp)
            .background(Color(0xFF0F172A), RoundedCornerShape(24.dp))
            .padding(vertical = 24.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
    ) {
        Text(
            text = "${(animatedValue * 10).roundToInt() / 10.0} kg",
            color = Color.White,
            fontSize = 44.sp,
            fontWeight = FontWeight.Black,
        )
        Spacer(Modifier.height(16.dp))
        Box(
            // ...
        ) {
            // Ruler ticks blurred at the left and right edges, sharp at center
            Canvas(
                modifier = Modifier
                    .fillMaxSize()
                    .blur(
                        blurRadiusSpec = BlurRadiusSpec.horizontalGradient(
                            stops = listOf(
                                BlurStop(fraction = 0.00f, radius = 14.dp),
                                BlurStop(fraction = 0.28f, radius = 0.dp),
                                BlurStop(fraction = 0.72f, radius = 0.dp),
                                BlurStop(fraction = 1.00f, radius = 14.dp),
                            ),
                        ),
                        edgeTreatment = BlurredEdgeTreatment.Unbounded,
                    ),
            ) {
                // Draw horizontal ruler ticks offset by `animatedValue`
                // ...
            }
            // ...
        }
    }
}

Şekil 2. Kenarlara yakın yerlerde bulanık, gösterge iğnesine yakın yerlerde ise net işaretlerin bulunduğu yatay cetvel ölçeği widget'ı.

linearGradient ile çapraz bulanıklık oluşturun

BlurRadiusSpec.linearGradient, katmanın koordinat uzayındaki start ve end DpOffset değerleri arasında bir çizgi segmenti boyunca bulanıklık yarıçapını değiştirir. Modifier.blur lambda bloğunun içinde, bir hero resim üzerinde sol üst köşeden sağ alt köşeye doğru çapraz aşamalı bulanıklaştırma uygulamak için BlurScope.size değerini okuyabilirsiniz. Bu işlem, sol üstteki özneyi tamamen net tutarken, yer paylaşımlı metnin arkasındaki sağ alt bölgeyi aşamalı olarak bulanıklaştırır:

@Composable
fun DiagonalLinearBlurCardExample() {
    Box(
        modifier = Modifier
            .wrapContentSize()
            .background(Color(0xFFF8FAFC))
            .padding(10.dp),
    ) {
        Image(
            painter = painterResource(id = R.drawable.dog),
            contentDescription = stringResource(id = R.string.dog_content_description),
            contentScale = ContentScale.Crop,
            modifier = Modifier
                .size(width = 300.dp, height = 380.dp)
                .blur {
                    blurRadiusSpec = BlurRadiusSpec.linearGradient(
                        start = DpOffset(0.dp, 0.dp),
                        end = DpOffset(size.width, size.height),
                        stops = listOf(
                            BlurStop(fraction = 0.00f, radius = 0.dp),
                            BlurStop(fraction = 0.50f, radius = 0.dp),
                            BlurStop(fraction = 0.75f, radius = 14.dp),
                            BlurStop(fraction = 1.00f, radius = 28.dp),
                        ),
                    )
                    edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(24.dp))
                },
        )
        // ...
    }
}

Sol üst köşesi net, sağ alt köşeye doğru giderek bulanıklaşan bir köpek portresi. Bulanık bölgenin üzerinde net, beyaz renkli başlık ve alt başlık metni yer alıyor.
Şekil 3. Sol üst köşesi net, sağ alt köşeye doğru giderek bulanıklaşan bir köpek portresi. Bulanık bölgenin üzerinde net, beyaz başlık ve alt başlık metni yer alıyor.

radialGradient ile odak noktası oluşturun

BlurRadiusSpec.radialGradient, bulanıklık yarıçapını bir odak noktasından dışarıya doğru değiştirerek dairesel bir spot ışığı efekti oluşturur. center öğesini DpOffset olarak ve fallOffRadius öğesini center öğesinden endRadius değerine ulaşılan Dp mesafesi olarak tanımlayın. center değerini DpOffset.Unspecified olarak bırakırsanız gradyan, composable'ın ortasına yerleştirilir. fallOffRadius değerini Dp.Unspecified olarak bırakırsanız varsayılan olarak katmanın daha küçük boyutunun yarısı kullanılır.

Örneğin, bir metin pasajına BlurRadiusSpec.radialGradient uygulayıp işaretçi sürükleme etkinliklerinden center değerini güncellemek, kullanıcının dairesel bir okuma spotunu paragraf üzerinde sürüklemesine ve etrafındaki metni bulanıklaştırmasına olanak tanır. Aşağıdaki örnekte bu durum gösterilmektedir:

@Composable
fun RadialSpotlightTextExample() {
    var touchOffset by remember { mutableStateOf(Offset.Unspecified) }
    Box(
        modifier = Modifier
            .size(width = 330.dp, height = 340.dp)
            .background(Color(0xFF0F172A), RoundedCornerShape(20.dp))
            .pointerInput(Unit) {
                detectDragGestures(
                    onDragStart = { offset -> touchOffset = offset },
                    onDrag = { change, _ -> touchOffset = change.position },
                )
            }
            .blur {
                val spotlightCenter = if (touchOffset.isSpecified) {
                    DpOffset(touchOffset.x.toDp(), touchOffset.y.toDp())
                } else {
                    DpOffset(x = size.width / 2, y = size.height / 2)
                }
                blurRadiusSpec = BlurRadiusSpec.radialGradient(
                    startRadius = 0.dp,
                    endRadius = 10.dp,
                    center = spotlightCenter,
                    fallOffRadius = 215.dp,
                )
                edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(20.dp))
            }
            .padding(22.dp),
    ) {
        // ...
    }
}

Şekil 4. İşaretçinin etrafında, dairenin kenarına doğru giderek bulanıklaşan keskin metinli dairesel bir alanın bulunduğu metin paragrafı.

Gölgelendirici ile özel bulanıklaştırma maskesi oluşturma

Doğrusal veya dairesel renk geçişlerinin ötesinde karmaşık uzamsal bulanıklık dağılımları (ör. tekrarlanan desenler, rastgele şekiller veya prosedürel gürültü) için BlurRadiusSpec.shader öğesine AGSL RuntimeShader gibi özel bir Shader iletin. Gölgelendirici, sol üst orijinden katman piksel koordinatlarında değerlendirilir ve örneklenen alfa kanalı (0..1) maxRadius ölçeklendirilir.

Gölgeleyiciyi ve BlurRadiusSpec.shader yapılandırmasını remember composable işlevini kullanarak bir kez oluşturun. Böylece, yeniden oluşturma işlemleri sırasında tek bir örnek yeniden kullanılır. Compose, her çözümlemede katman boyutuyla yapılandırma bloğunu çağırır. Boyuta bağlı uniform'ları burada ayarlarsınız:

@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@Composable
fun ShaderBlurExample() {
    // Creates 6 diagonal frosted-glass bands across the image.
    val maskShader = remember {
        RuntimeShader(
            """
            uniform float2 size;
            half4 main(float2 coord) {
                float2 uv = coord / size;
                float band = smoothstep(0.4, 0.6, fract((uv.x + uv.y) * 3.0));
                return half4(0.0, 0.0, 0.0, half(band));
            }
            """.trimIndent(),
        )
    }
    val maskBlurSpec = remember(maskShader) {
        BlurRadiusSpec.shader(maxRadius = 24.dp) { sizePx ->
            maskShader.setFloatUniform("size", sizePx.width, sizePx.height)
            maskShader
        }
    }
    Image(
        painter = painterResource(id = R.drawable.dog),
        contentDescription = stringResource(id = R.string.dog_content_description),
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .size(150.dp)
            .blur(blurRadiusSpec = maskBlurSpec),
    )
}

Özel gölgelendirici maskesiyle oluşturulan çapraz buzlu cam bulanıklık bantları içeren bir köpek resmi.
Şekil 5. Özel gölgelendirici maskesiyle oluşturulmuş, çapraz buzlu cam bulanıklığı bantları içeren bir köpek resmi.