تخصيص صورة

يمكنك تخصيص الصور باستخدام خصائص في عنصر Image قابل للإنشاء (contentScale، colorFilter). يمكنك أيضًا تطبيق معدِّلات حالية لتطبيق تأثيرات مختلفة على Image. يمكن استخدام المعدِّلات مع أي عنصر قابل للإنشاء، وليس فقط مع العنصر القابل للإنشاء Image، بينما contentScale وcolorFilter هما مَعلمتان صريحتان في العنصر القابل للإنشاء Image.

مقياس المحتوى

حدِّد خيار contentScale لاقتصاص صورة أو تغيير طريقة تغيير حجمها داخل حدودها. بشكلٍ تلقائي، إذا لم تحدّد خيار contentScale، سيتم استخدام ContentScale.Fit.

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

val imageModifier = Modifier
    .size(150.dp)
    .border(BorderStroke(1.dp, Color.Black))
    .background(Color.Yellow)
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Fit,
    modifier = imageModifier
)

يؤدي ضبط خيارات ContentScale مختلفة إلى الحصول على نتائج مختلفة. يساعدك الجدول التالي في اختيار وضع ContentScale الصحيح:

الصورة المصدر مصدر الصورة الشخصية الذي يعرض كلبًا مصدر الصورة الأفقية الذي يعرض كلبًا مختلفًا
ContentScale النتيجة - صورة عمودية: النتيجة - صورة أفقية:
ContentScale.Fit: تغيير حجم الصورة بشكل موحّد مع الحفاظ على نسبة العرض إلى الارتفاع (الإعداد التلقائي) إذا كان المحتوى أصغر من الحجم، يتم تكبير الصورة لتناسب الحدود. صورة كلب تم تغيير حجمها بشكل موحّد صورة أفقية لكلب تم تحجيمها بشكل موحّد
ContentScale.Crop: اقتصاص الصورة في وسط المساحة المتاحة صورة عمودية تم اقتصاصها لملء إطار مربّع، مع عرض الجزء المركزي فقط من الصورة صورة أفقية تم اقتصاصها لملء إطار مربّع، مع عرض الجزء المركزي فقط من الصورة
ContentScale.FillHeight: تغيير حجم المصدر مع الحفاظ على نسبة العرض إلى الارتفاع لكي تتطابق الحدود مع ارتفاع الوجهة صورة عمودية تم تغيير حجمها لملء ارتفاع إطار مربّع، وتظهر الصورة الكاملة مع خلفية صفراء على اليمين واليسار. صورة أفقية تم تغيير حجمها لملء ارتفاع إطار مربّع، مع اقتصاص الجوانب
ContentScale.FillWidth: تغيير حجم المصدر مع الحفاظ على نسبة العرض إلى الارتفاع لكي تتطابق الحدود مع عرض الوجهة صورة عمودية تم تغيير حجمها لملء عرض إطار مربّع، مع اقتصاص الجزء العلوي والسفلي صورة أفقية تم تغيير حجمها لملء عرض إطار مربّع، وتظهر الصورة الكاملة مع خلفية صفراء في الأعلى والأسفل.
ContentScale.FillBounds: لتغيير حجم المحتوى عموديًا وأفقيًا بشكل غير منتظم لملء حدود الوجهة (ملاحظة: يؤدي ذلك إلى تشويه الصور إذا وضعتها في حاويات لا تتطابق مع النسبة الدقيقة للصورة). صورة عمودية مشوّهة لملء إطار مربّع بالكامل، ما يؤدي إلى تمديد الصورة صورة أفقية مشوّهة لملء إطار مربّع بالكامل، ما يؤدي إلى تمديد الصورة
ContentScale.Inside: تغيير حجم المصدر للحفاظ على نسبة العرض إلى الارتفاع داخل حدود الوجهة إذا كان المصدر أصغر من الوجهة أو يساويها في كلا البُعدَين، سيتصرف بشكل مشابه لـ None. سيتم دائمًا تضمين المحتوى ضمن الحدود. إذا كان المحتوى أصغر من الحدود، لن يتم تطبيق أي تغيير في الحجم. حجم صورة المصدر أكبر من الحدود: صورة عمودية كانت في الأصل أكبر من حدودها المربّعة، وتم تصغيرها لتناسبها مع الحفاظ على نسبة العرض إلى الارتفاع، وتظهر خلفية صفراء على الجانبين. حجم صورة المصدر أصغر من الحدود: صورة عمودية أصغر من حدودها المربعة، معروضة بحجمها الأصلي داخل الإطار، وتظهر خلفية صفراء حولها حجم صورة المصدر أكبر من الحدود: صورة أفقية كانت في الأصل أكبر من حدودها المربعة، وتم تصغير حجمها لتناسبها مع الحفاظ على نسبة العرض إلى الارتفاع، وتظهر خلفية صفراء في الأعلى والأسفل. حجم صورة المصدر أصغر من الحدود: صورة أفقية كانت في الأصل أصغر من حدودها المربعة، ويتم عرضها بحجمها الأصلي داخل الإطار، مع خلفية صفراء حولها
ContentScale.None: عدم تطبيق أي تغيير في الحجم على المصدر إذا كان المحتوى أصغر من حدود الوجهة، لن يتم تكبيره ليناسب المساحة. حجم صورة المصدر أكبر من الحدود: صورة عمودية كانت في الأصل أكبر من حدودها المربعة، وتم عرضها بحجمها الأصلي مع أجزاء تمتد إلى ما بعد أعلى وأسفل الإطار حجم صورة المصدر أصغر من الحدود: صورة عمودية كانت في الأصل أصغر من حدودها المربعة، ويتم عرضها بحجمها الأصلي داخل الإطار، مع خلفية صفراء حولها حجم صورة المصدر أكبر من الحدود: صورة أفقية، كانت في الأصل أكبر من حدودها المربّعة، معروضة بحجمها الأصلي، مع أجزاء تمتد إلى ما بعد يسار الإطار ويمينه حجم صورة المصدر أصغر من الحدود: صورة أفقية كانت في الأصل أصغر من حدودها المربعة، ويتم عرضها بحجمها الأصلي داخل الإطار، مع خلفية صفراء حولها

قص Image قابلة للإنشاء إلى شكل

لجعل الصورة تناسب شكلاً، استخدِم المعدِّل clip المضمّن. لاقتصاص صورة في شكل دائرة، استخدِم Modifier.clip(CircleShape):

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(200.dp)
        .clip(CircleShape)
)

صورة لكلب تم اقتصاصها على شكل دائرة مثالية
الشكل 1. اقتصاص صورة باستخدام "CircleShape"

بالنسبة إلى شكل الزاوية الدائرية، استخدِم Modifier.clip(RoundedCornerShape(16.dp))، مع حجم الزوايا التي تريد أن تكون دائرية:

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(200.dp)
        .clip(RoundedCornerShape(16.dp))
)

صورة مربّعة لكلب تم قصّها بزوايا مستديرة
الشكل 2 اقتصاص صورة باستخدام "RoundedCornerShape"

يمكنك أيضًا إنشاء شكل قص خاص بك من خلال توسيع Shape وتوفير Path للشكل الذي تريد القص حوله:

class SquashedOval : Shape {
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        val path = Path().apply {
            // We create an Oval that starts at ¼ of the width, and ends at ¾ of the width of the container.
            addOval(
                Rect(
                    left = size.width / 4f,
                    top = 0f,
                    right = size.width * 3 / 4f,
                    bottom = size.height
                )
            )
        }
        return Outline.Generic(path = path)
    }
}

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(200.dp)
        .clip(SquashedOval())
)

صورة مربّعة لكلب تم قصها على شكل بيضاوي مخصّص
الشكل 3. قص صورة باستخدام شكل مسار مخصّص

إضافة حدود إلى عنصر Image قابل للإنشاء

من العمليات الشائعة دمج Modifier.border() مع Modifier.clip() لإنشاء إطار حول صورة:

val borderWidth = 4.dp
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(150.dp)
        .border(
            BorderStroke(borderWidth, Color.Yellow),
            CircleShape
        )
        .padding(borderWidth)
        .clip(CircleShape)
)

صورة مربّعة لكلب تم اقتصاصها على شكل دائرة، مع حدود صفراء حول الشكل الدائري
الشكل 4 صورة مقصوصة مع حدود حولها

لإنشاء حد متدرّج، يمكنك استخدام واجهة برمجة التطبيقات Brush لرسم حد متدرّج بألوان قوس قزح حول الصورة:

val rainbowColorsBrush = remember {
    Brush.sweepGradient(
        listOf(
            Color(0xFF9575CD),
            Color(0xFFBA68C8),
            Color(0xFFE57373),
            Color(0xFFFFB74D),
            Color(0xFFFFF176),
            Color(0xFFAED581),
            Color(0xFF4DD0E1),
            Color(0xFF9575CD)
        )
    )
}
val borderWidth = 4.dp
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(150.dp)
        .border(
            BorderStroke(borderWidth, rainbowColorsBrush),
            CircleShape
        )
        .padding(borderWidth)
        .clip(CircleShape)
)

صورة دائرية لكلب مع حدود متدرّجة الألوان على شكل قوس قزح حول الشكل الدائري
الشكل 5 حد دائري بتدرّج ألوان قوس قزح

ضبط نسبة عرض إلى ارتفاع مخصّصة

لتحويل صورة إلى نسبة عرض إلى ارتفاع مخصّصة، استخدِم Modifier.aspectRatio(16f/9f) لتوفير نسبة مخصّصة لصورة (أو أي عنصر قابل للإنشاء).

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    modifier = Modifier.aspectRatio(16f / 9f)
)

صورة مربّعة لكلب تم تحويلها إلى نسبة عرض إلى ارتفاع تبلغ 16:9، ما يجعلها أعرض وأقصر.
الشكل 6. استخدام Modifier.aspectRatio(16f/9f) على Image.

فلتر الألوان: تحويل ألوان البكسل في الصورة

يحتوي العنصر Image القابل للإنشاء على مَعلمة colorFilter يمكنها تغيير ناتج وحدات البكسل الفردية في صورتك.

تلوين الصور

يؤدي استخدام ColorFilter.tint(color, blendMode) إلى تطبيق وضع المزج مع اللون المحدّد على العنصر القابل للإنشاء Image. يستخدم ColorFilter.tint(color, blendMode) BlendMode.SrcIn لتلوين المحتوى، ما يعني أنّ اللون المقدَّم يظهر في المكان الذي يتم فيه عرض الصورة على الشاشة. ويكون ذلك مفيدًا للرموز والصور المتجهة التي يجب أن يكون لها مظهر مختلف.

Image(
    painter = painterResource(id = R.drawable.baseline_directions_bus_24),
    contentDescription = stringResource(id = R.string.bus_content_description),
    colorFilter = ColorFilter.tint(Color.Yellow)
)

صورة لحافلة تم تطبيق لون أصفر عليها
الشكل 7 تم تطبيق ColorFilter.tint باستخدام BlendMode.SrcIn.

تؤدي BlendMode الأخرى إلى تأثيرات مختلفة. على سبيل المثال، يؤدي ضبط BlendMode.Darken مع Color.Green على صورة إلى ظهور النتيجة التالية:

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    colorFilter = ColorFilter.tint(Color.Green, blendMode = BlendMode.Darken)
)

صورة كلب تم تطبيق لون أخضر عليها باستخدام BlendMode.Darken، ما أدّى إلى ظهور درجات أغمق من اللون الأخضر
الشكل 8Color.Green tint مع BlendMode.Darken.

اطّلِع على BlendMode مستندات المرجع للحصول على مزيد من المعلومات حول أوضاع المزج المختلفة المتاحة.

تطبيق فلتر Image باستخدام مصفوفة الألوان

حوِّل صورتك باستخدام الخيار "مصفوفة الألوان" ColorFilter. على سبيل المثال، لتطبيق فلتر أبيض وأسود على صورك، يمكنك استخدام ColorMatrix وضبط التشبع على 0f.

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    colorFilter = ColorFilter.colorMatrix(ColorMatrix().apply { setToSaturation(0f) })
)

صورة لكلب تم تطبيق فلتر أبيض وأسود عليها، ما أدى إلى إزالة كل تشبّع الألوان
الشكل 9 مصفوفة الألوان مع تشبّع 0 (صورة بالأبيض والأسود).

ضبط التباين أو السطوع في عنصر Image قابل للإنشاء

لتغيير التباين والسطوع في صورة، يمكنك استخدام ColorMatrix لتغيير القيم:

val contrast = 2f // 0f..10f (1 should be default)
val brightness = -180f // -255f..255f (0 should be default)
val colorMatrix = floatArrayOf(
    contrast, 0f, 0f, 0f, brightness,
    0f, contrast, 0f, 0f, brightness,
    0f, 0f, contrast, 0f, brightness,
    0f, 0f, 0f, 1f, 0f
)
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    colorFilter = ColorFilter.colorMatrix(ColorMatrix(colorMatrix))
)

صورة لكلب مع زيادة في السطوع والتباين، ما يجعلها تبدو أكثر حيوية
الشكل 10 تم تعديل سطوع الصورة وتباينها باستخدام ColorMatrix.

قلب ألوان عنصر Image قابل للإنشاء

لعكس ألوان الصورة، اضبط ColorMatrix لعكس الألوان:

val colorMatrix = floatArrayOf(
    -1f, 0f, 0f, 0f, 255f,
    0f, -1f, 0f, 0f, 255f,
    0f, 0f, -1f, 0f, 255f,
    0f, 0f, 0f, 1f, 0f
)
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    colorFilter = ColorFilter.colorMatrix(ColorMatrix(colorMatrix))
)

كلب بألوان مقلوبة، ما يؤدي إلى ظهور تأثير سلبي
الشكل 11. ألوان مقلوبة في الصورة

تمويه عنصر Image قابل للإنشاء

لتشويش صورة، استخدِم Modifier.blur() مع توفير radiusX وradiusY، اللذين يحدّدان نصف قطر التشويش في الاتجاه الأفقي والعمودي على التوالي.

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 = 10.dp,
            edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(8.dp))
        )
)

صورة لكلب تم تطبيق تأثير تمويه قوي عليها، ما يجعلها تبدو غير واضحة وغير مركّزة.
الشكل 12 تم تطبيق BlurEffect على صورة.

عند التمويه باستخدام Images، يُنصح باستخدام BlurredEdgeTreatment(Shape) بدلاً من BlurredEdgeTreatment.Unbounded، لأنّ الأخير يُستخدم لتمويه العروض العشوائية التي من المتوقّع أن يتم عرضها خارج حدود المحتوى الأصلي. بالنسبة إلى الصور، من المحتمل ألا يتم عرضها خارج حدود المحتوى، بينما قد يتطلّب تمويه مستطيل دائري هذا التمييز.

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

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 = 10.dp,
            edgeTreatment = BlurredEdgeTreatment.Unbounded
        )
        .clip(RoundedCornerShape(8.dp))
)

صورة غير واضحة لكلب، حيث يمتد التشويش إلى ما بعد حدود الصورة الأصلية، ما يجعل الحواف غير واضحة.
الشكل 13. BlurEdgeTreatment.Unbounded.