সাধারণ অস্পষ্ট ব্যবহারের কেস

সাধারণ UI প্যাটার্নের জন্য কীভাবে Modifier.blur, BlurRadiusSpec, BlurStop এবং BlurScope একত্রিত করতে হয় তা নিম্নলিখিত বিভাগে দেখানো হয়েছে। এইসব API-এর ব্যাপারে জানতে, 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 পাস করুন, যেমন AGSL RuntimeShader, BlurRadiusSpec.shader-এ। শেডার, উপরের-বাঁদিকের উৎস থেকে লেয়ার পিক্সেল কোঅর্ডিনেটে মূল্যায়ন করে এবং এর স্যাম্পেল করা আলফা চ্যানেল (0..1) maxRadius স্কেল করে।

BlurRadiusSpec.shader কনফিগারেশন ও শেডার একবার তৈরি করুন, এর জন্য remember কম্পোজেবল ফাংশন ব্যবহার করুন, যাতে একটি ইনস্ট্যান্স একাধিক রিকম্পোজিশন জুড়ে ব্যবহার করা যায়। 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),
    )
}

কাস্টম শেডার মাস্কের মাধ্যমে তৈরি করা ডায়াগনাল ফ্রস্টেড-গ্লাস ব্লার ব্যান্ড সহ কুকুরের ছবি।
ছবি ৫. কাস্টম শেডার মাস্কের মাধ্যমে পরিচালিত ডায়াগনাল ফ্রস্টেড-গ্লাস ব্লার ব্যান্ড সহ কুকুরের ছবি।