धुंधला करने की सुविधा के इस्तेमाल के सामान्य उदाहरण

यहां दिए गए सेक्शन में, यूज़र इंटरफ़ेस (यूआई) के सामान्य पैटर्न के लिए, Modifier.blur, BlurRadiusSpec, BlurStop, और BlurScope को जोड़ने का तरीका बताया गया है. इन एपीआई के बारे में जानने के लिए, Compose में ब्लर करना लेख पढ़ें.

स्क्रोल या खींचकर छोड़े जा सकने वाले कॉन्टेंट के किनारों को धुंधला करना

स्क्रोल करने वाली सूची, कैरसेल या पिकर दिखाते समय, मल्टी-स्टॉप प्रोग्रेसिव ब्लर का इस्तेमाल किया जा सकता है. इससे कंटेनर के किनारों के आस-पास मौजूद आइटम को धुंधला किया जा सकता है. साथ ही, बीच वाले हिस्से को साफ़ तौर पर फ़ोकस में रखा जा सकता है.

स्क्रोल की जा रही सूची के सबसे ऊपर और सबसे नीचे के किनारों को फ़ेड करें

वर्टिकल लिस्ट के व्यूपोर्ट में आइटम के स्क्रोल होने पर, उन्हें सॉफ़्ट करने के लिए, LazyColumn में BlurStop एंट्री के साथ BlurRadiusSpec.verticalGradient लागू करें. यहां दिए गए उदाहरण में, गाने के बोल एक-एक करके स्क्रोल होते हैं. 0.dp स्टॉप, 0.42f और 0.58f के बीच में होते हैं. इससे, गाने की मौजूदा लाइन स्क्रीन के बीच में साफ़ तौर पर दिखती है. वहीं, ऊपर और नीचे की लाइनें धीरे-धीरे धुंधली हो जाती हैं:

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

पहली इमेज. गाने के बोल की लाइनों की वर्टिकल सूची. इसमें सबसे ऊपर और सबसे नीचे की लाइनें धुंधली हैं, जबकि बीच की लाइन साफ़ तौर पर दिख रही है.

हॉरिज़ॉन्टल कंट्रोल के बाएं और दाएं किनारों को फ़ेड करें

इसी तरह, हॉरिज़ॉन्टल तौर पर स्क्रोल या खींचकर छोड़े जा सकने वाले कॉम्पोनेंट के बीच में फ़ोकस करने के लिए, BlurStop एंट्री के साथ BlurRadiusSpec.horizontalGradient लागू करें. जैसे, व्हील पिकर, कैरसेल या मेज़रमेंट स्केल. खींचने और छोड़ने लायक इस वेट स्केल में, बाईं और दाईं ओर के किनारे धुंधले हो जाते हैं. हालांकि, बीच में मौजूद इंडिकेटर सुई के आस-पास के टिक और नंबर पूरी तरह से साफ़ दिखते हैं:

@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`
                // ...
            }
            // ...
        }
    }
}

दूसरी इमेज. हॉरिज़ॉन्टल रूलर स्केल विजेट, जिसमें किनारों के पास धुंधले टिक मार्क और इंडिकेटर सुई के पास शार्प टिक दिख रहे हैं.

linearGradient की मदद से, डायगनल ब्लर इफ़ेक्ट बनाएं

BlurRadiusSpec.linearGradient, लेयर के कोऑर्डिनेट स्पेस में start और end DpOffset वैल्यू के बीच, लाइन सेगमेंट के साथ ब्लर रेडियस को बदलता है. Modifier.blur लैम्ब्डा ब्लॉक में, BlurScope.size को पढ़ा जा सकता है. इससे हीरो इमेज पर, सबसे ऊपर बाएं कोने से सबसे नीचे दाएं कोने तक, डायगनल प्रोग्रेसिव ब्लर लागू किया जा सकता है. इससे सबसे ऊपर बाईं ओर मौजूद सब्जेक्ट पूरी तरह से साफ़ दिखता है, जबकि ओवरले किए गए टेक्स्ट के पीछे मौजूद निचले दाएं हिस्से को धीरे-धीरे धुंधला किया जाता है:

@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))
                },
        )
        // ...
    }
}

एक कुत्ते की पोर्ट्रेट इमेज, जो ऊपर बाईं ओर साफ़ दिख रही है और नीचे दाईं ओर धुंधली होती जा रही है. धुंधले हिस्से पर, साफ़ तौर पर दिखने वाला सफ़ेद टाइटल और सबटाइटल टेक्स्ट ओवरले किया गया है.
तीसरी इमेज. एक कुत्ते की पोर्ट्रेट इमेज, जो ऊपर बाईं ओर साफ़ दिख रही है और नीचे दाईं ओर धुंधली होती जा रही है. धुंधले हिस्से पर, साफ़ तौर पर दिखने वाला सफ़ेद टाइटल और सबटाइटल टेक्स्ट ओवरले किया गया है.

radialGradient की मदद से, फ़ोकस स्पॉटलाइट बनाएं

BlurRadiusSpec.radialGradient, फ़ोकल पॉइंट से बाहर की ओर ब्लर रेडियस को बदलकर, गोल स्पॉटलाइट इफ़ेक्ट बनाता है. center को DpOffset के तौर पर तय करें और fallOffRadius को center से Dp दूरी के तौर पर तय करें, जिस पर endRadius पहुंचा है. अगर center को DpOffset.Unspecified के तौर पर छोड़ा जाता है, तो ग्रेडिएंट को कंपोज़ेबल के बीच में रखा जाता है. अगर fallOffRadius को Dp.Unspecified के तौर पर छोड़ा जाता है, तो यह डिफ़ॉल्ट रूप से लेयर के छोटे डाइमेंशन के आधे हिस्से पर सेट हो जाता है.

उदाहरण के लिए, टेक्स्ट के किसी पैसेज पर BlurRadiusSpec.radialGradient लागू करने और पॉइंटर को खींचकर छोड़ने के इवेंट से center को अपडेट करने पर, उपयोगकर्ता पैराग्राफ़ पर गोल आकार की रीडिंग स्पॉटलाइट को खींचकर छोड़ सकता है. इससे आस-पास का टेक्स्ट धुंधला हो जाता है, जैसा कि इस उदाहरण में दिखाया गया है:

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

चौथी इमेज. टेक्स्ट का एक पैराग्राफ़, जिसमें पॉइंटर के आस-पास का टेक्स्ट साफ़ तौर पर दिख रहा है. हालांकि, सर्कल के किनारे की ओर जाने पर टेक्स्ट धुंधला होता जा रहा है.

शेडर की मदद से, पसंद के मुताबिक ब्लर मास्क बनाना

लीनियर या रेडियल ग्रेडिएंट के अलावा, मुश्किल स्पेशल ब्लर डिस्ट्रिब्यूशन के लिए, कस्टम Shader पास करें. जैसे, दोहराए जाने वाले पैटर्न, मनचाहे आकार या प्रोसीजरल नॉइज़. जैसे, BlurRadiusSpec.shader के लिए AGSL RuntimeShader. शेडर, लेयर पिक्सल कोऑर्डिनेट में सबसे ऊपर बाईं ओर से आकलन करता है. साथ ही, इसका सैंपल किया गया ऐल्फ़ा चैनल (0..1), maxRadius को स्केल करता है.

remember ऐप्लिकेशन बनाने की सुविधा का इस्तेमाल करके, शेडर और BlurRadiusSpec.shader कॉन्फ़िगरेशन को एक बार बनाएं. इससे, एक ही इंस्टेंस को फिर से कंपोज़ करने के दौरान इस्तेमाल किया जा सकता है. Compose, हर रिज़ॉल्व पर लेयर के साइज़ के साथ कॉन्फ़िगरेशन ब्लॉक को शुरू करता है. यहां साइज़ के हिसाब से यूनिफ़ॉर्म सेट किए जाते हैं:

@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),
    )
}

कस्टम शेडर मास्क की मदद से, कुत्ते की इमेज पर डायगनल फ़्रॉस्टेड-ग्लास ब्लर बैंड लागू किया गया है.
पांचवीं इमेज. एक कुत्ते की इमेज, जिसमें कस्टम शेडर मास्क की मदद से, डायगनल फ़्रॉस्टेड-ग्लास ब्लर बैंड जोड़े गए हैं.