تخصيص صورة

يمكنك تخصيص الصور باستخدام خصائص في عنصر 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.