التمويه في Compose

تساعد تأثيرات التمويه في تنعيم التفاصيل المرئية، وإنشاء عمق مجال فوتوغرافي، وجذب التركيز إلى عناصر في واجهة المستخدم في المقدّمة. في Jetpack Compose، استخدِم Modifier.blur لتمويه المحتوى المرسوم داخل دالة مركّبة، بما في ذلك الصور والأشكال والنصوص وحاويات التنسيق. يؤدي تطبيق Modifier.blur إلى عرض الدالة المركّبة في طبقة رسومات منفصلة.

على اليمين: الصورة الأصلية. في الوسط: صورة تم تطبيق تمويه موحّد على سطحها بالكامل. على اليسار: الصورة مع تمويه تدريجي يكون حادًا في الأعلى ويزداد نحو الأسفل.
الشكل 1. على اليمين: الصورة الأصلية. في الوسط: الصورة مع تطبيق تمويه موحّد على السطح بأكمله. على اليسار: الصورة مع تمويه تدريجي يكون حادًا في الأعلى ويزداد نحو الأسفل.

اعتمادًا على أهداف التصميم، يمكنك تغيير التمويه بطريقتين:

  • التمويه الموحّد: يطبّق نطاق تمويه ثابتًا على الدالة المركّبة بأكملها، إما بالتساوي على كلا المحورَين أو بنطاقَين أفقي وعمودي مستقلَّين (radiusX وradiusY).
  • التمويه التدريجي: يغيّر نصف قطر التمويه مكانيًا في جميع أنحاء الدالة المركّبة باستخدام تدرجات BlurRadiusSpec أو Shader مخصّص.

تطبيق تمويه موحّد

لتطبيق تمويه ثابت على دالة مركّبة بأكملها، مرِّر نصف قطر Dp إلى Modifier.blur. يمكنك تمرير قيمة radius واحدة لتمويه المحتوى بالتساوي على طول المحورَين الأفقي (X) والعمودي (Y):

@Composable
fun UniformBlurExample() {
    Image(
        painter = painterResource(id = R.drawable.dog),
        contentDescription = stringResource(id = R.string.dog_content_description),
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .size(150.dp)
            .blur(
                radius = 8.dp,
                edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(8.dp)),
            ),
    )
}

كلب مموّه بشكل موحّد على المحورَين الأفقي والعمودي
الشكل 2. كلب مموّه بشكل موحّد على المحورَين الأفقي والعمودي

لإنشاء تأثير تمويه الحركة الاتجاهي، مرِّر قيمتَي radiusX وradiusY منفصلتَين إلى Modifier.blur. يجب أن تكون قيمة كل من radiusX وradiusY أكبر من 0.dp لتطبيق تأثير التمويه، كما هو موضّح في المثال التالي:

@Composable
fun DirectionalBlurExample() {
    Image(
        painter = painterResource(id = R.drawable.dog),
        contentDescription = stringResource(id = R.string.dog_content_description),
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .size(150.dp)
            .blur(
                radiusX = 10.dp,
                radiusY = 2.dp,
                edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(8.dp)),
            ),
    )
}

كلب مع تأثير تمويه حركة أفقي قوي
الشكل 3. صورة مربّعة لكلب مع تأثير تمويه أفقي قوي للحركة

تطبيق تمويه تدريجي

يؤدي التمويه التدريجي إلى تغيير نصف قطر التمويه في الدالة المركّبة، ما يؤدي إلى إنشاء انتقال سلس بين المناطق الحادة والمموّهة.

مرِّر BlurRadiusSpec إلى Modifier.blur. على سبيل المثال، استخدِم BlurRadiusSpec.verticalGradient مع startRadius = 0.dp وendRadius = 6.dp لإبقاء الجزء العلوي من الصورة واضحًا مع تمويهه تدريجيًا نحو الأسفل، كما هو موضّح في المثال التالي:

@Composable
fun ProgressiveBlurExample() {
    Image(
        painter = painterResource(id = R.drawable.dog),
        contentDescription = stringResource(id = R.string.dog_content_description),
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .size(150.dp)
            .blur(
                // Sharp at the top (0.dp), progressively blurred toward the bottom (6.dp)
                blurRadiusSpec = BlurRadiusSpec.verticalGradient(
                    startRadius = 0.dp,
                    endRadius = 6.dp,
                ),
                edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(8.dp)),
            ),
    )
}

كلب يظهر بوضوح في الأعلى ويصبح مموّهًا تدريجيًا في الأسفل
الشكل 4. صورة لكلب واضحة في الأعلى وتصبح مموّهة تدريجيًا في الأسفل

تحديد تدرّجات التمويه باستخدام BlurRadiusSpec

في BlurRadiusSpec، يتم ضبط القياسات في Dp ويتم تعديلها تلقائيًا وفقًا لحجم الطبقة وكثافة العرض عند رسمها. يبلغ الحد الأقصى للتمويه المتفاوت مكانيًا 150 بكسل بعد التحويل، بينما لا يوجد حد أقصى في BlurRadiusSpec.uniform.

يسرد الجدول التالي دوال المصنع المتاحة على BlurRadiusSpec:

مصنع واحد (BlurRadiusSpec) الوصف
BlurRadiusSpec.verticalGradient يغيّر هذا الخيار نصف قطر التمويه بسلاسة عموديًا من الأعلى (0f) إلى الأسفل (1f) على مستوى الطبقة.
BlurRadiusSpec.horizontalGradient يغيّر هذا الخيار بسلاسة نصف قطر التمويه أفقيًا من الحافة اليسرى (0f) إلى الحافة اليمنى (1f).
BlurRadiusSpec.linearGradient تطبّق هذه السمة تأثير انتقال تمويهي اتجاهي على طول خط مستقيم يربط بين إحداثيات DpOffset معيّنة.
BlurRadiusSpec.radialGradient ينشر التمويه من نقطة التركيز نحو حدود fallOffRadius.
BlurRadiusSpec.uniform يتم تطبيق نصف قطر تمويه متساوٍ على الطبقة بأكملها.
BlurRadiusSpec.shader يستخدم قناة ألفا مخصّصة في Shader للتحكّم في maxRadius وتغيير حجمه عند كل بكسل.

تخصيص توزيع التمويه باستخدام BlurStop

يتم استيفاء التمويهات المتدرجة العادية خطيًا بين 0f و1f. لتخصيص توزيع التمويه على سطح معيّن، مثل تمويه حواف متعددة أو إبقاء الجزء الأوسط واضحًا تمامًا، يمكنك تمرير List<BlurStop> يحتوي على ما بين 2 و16 إدخال BlurStop إلى verticalGradient أو horizontalGradient أو linearGradient أو radialGradient. حدِّد ما يلي لكل إدخال في BlurStop:

  • ‫fraction: الموضع النسبي على طول التدرج من 0.0f إلى 1.0f. يتم ترتيب محطات التوقف تلقائيًا حسب الكسر.
  • ‫radius: نطاق التعتيم في Dp المطبَّق في موضع الجزء المحدّد

على سبيل المثال، تعمل أربع نقاط توقّف على تمويه الحواف العلوية والسفلية للصورة مع الحفاظ على الوسط حادًا تمامًا، كما هو موضّح في المثال التالي:

@Composable
fun MultiStopBlurExample() {
    Image(
        painter = painterResource(id = R.drawable.dog),
        contentDescription = stringResource(id = R.string.dog_content_description),
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .size(150.dp)
            .blur(
                // Blurred at the top and bottom edges, sharp in the middle (0.3f..0.7f)
                blurRadiusSpec = BlurRadiusSpec.verticalGradient(
                    stops = listOf(
                        BlurStop(fraction = 0.0f, radius = 20.dp),
                        BlurStop(fraction = 0.3f, radius = 0.dp),
                        BlurStop(fraction = 0.7f, radius = 0.dp),
                        BlurStop(fraction = 1.0f, radius = 20.dp),
                    ),
                ),
                edgeTreatment = BlurredEdgeTreatment.Unbounded,
            ),
    )
}

كلب بحواف علوية وسفلية مموّهة مع إبقاء الشريط الأفقي الأوسط في بؤرة تركيز واضحة
الشكل 5. صورة لكلب مع تمويه الحواف العلوية والسفلية مع الحفاظ على تركيز واضح على الشريط الأفقي الأوسط.

ضبط خصائص الطبقة باستخدام BlurScope

بدلاً من تمرير blurRadiusSpec مباشرةً، يمكنك تمرير مجموعة إعدادات إلى Modifier.blur { ... }. يتم تشغيل هذه المجموعة داخل BlurScope، ما يمنحك وصولاً مباشرًا إلى كثافة التنسيق والسمات التالية:

  • ‫size: DpSize: يمثّل العرض والارتفاع اللذين تم قياسهما للطبقة المموّهة في Dp، والتي تحدّد مساحة الإحداثيات لهندسة التدرج.
  • blurRadiusSpec: BlurRadiusSpec: إعدادات نطاق التعتيم على مستوى السطح القيمة التلقائية هي BlurRadiusSpec.uniform(0.dp) (بدون تمويه).
  • edgeTreatment: BlurredEdgeTreatment: الاستراتيجية المستخدَمة لأخذ عيّنات من وحدات البكسل خارج حدود المحتوى واقتصاصها القيمة التلقائية هي BlurredEdgeTreatment.Rectangle.
  • ‫alpha: Float: تعتيم الطبقة المموّهة في النطاق 0f..1f. القيمة التلقائية هي 1f.

بما أنّ مجموعة الرموز البرمجية BlurScope يتم تشغيلها خلال مرحلة طبقة الرسومات، بعد القياس والتنسيق، يمكنك حساب هندسة التدرج من size بدون بدء إعادة الإنشاء.

التحكّم في اقتصاص الحواف باستخدام BlurredEdgeTreatment

بما أنّ التمويه يأخذ عيّنات من وحدات البكسل المجاورة ضمن نطاق التمويه، فإنّ الناتج المموّه يمتد إلى ما بعد حدود المحتوى الأصلي بمقدار نطاق التمويه. BlurredEdgeTreatment يحدّد كيفية أخذ عيّنات من وحدات البكسل خارج الحدود الأصلية وما إذا كان سيتم اقتصاص النتيجة لتتلاءم مع شكل معيّن.

تعمل ميزة "BlurredEdgeTreatment" مع كل من التمويه الموحّد والتدريجي:

BlurredEdgeTreatment السلوك الناتج
BlurredEdgeTreatment.Rectangle (تلقائي) يتم اقتصاص نتيجة التمويه إلى الحدود المستطيلة للمحتوى الأصلي ويتم أخذ عيّنات من وحدات البكسل الأقرب إلى الحافة (TileMode.Clamp). صورة لكلب مموّهة ومقصوصة على شكل مستطيل حاد
BlurredEdgeTreatment(shape) يتم اقتصاص نتيجة التمويه إلى Shape المحدّد (مثل RoundedCornerShape(8.dp)) ويتم أخذ عيّنات من وحدات البكسل الأقرب إلى الحافة (TileMode.Clamp). يحافظ على حدّة نتيجة التمويه عند حدود الشكل بدون تسرّب خارج الحدود الأصلية. صورة مموّهة لكلب تم اقتصاصها على شكل زوايا مستديرة وحواف حادة
BlurredEdgeTreatment.Unbounded لا يتم اقتصاص نتيجة التمويه (TileMode.Decal). وتكون وحدات البكسل خارج حدود المحتوى سوداء شفافة، ما يجعل الحواف الخارجية للصورة تبدو ضبابية ومموّهة خارج الحدود الأصلية. صورة مموّهة لكلب تتلاشى حوافها بنعومة خارج الحدود الأصلية.

للاطّلاع على كيفية دمج واجهات برمجة التطبيقات هذه في أنماط واجهة المستخدم الكاملة، مثل تلاشي حواف المحتوى الذي يتم الانتقال إليه أو تسليط الضوء على نقطة تركيز أو إخفاء التمويه باستخدام تظليل مخصّص، يُرجى الاطّلاع على حالات الاستخدام الشائعة للتمويه.