تخصيص صورة

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

تؤدي BlendModes الأخرى إلى تأثيرات مختلفة. على سبيل المثال، يؤدي ضبط 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.