تخصيص صورة

يمكن تخصيص الصور باستخدام خصائص في عنصر Image قابل للإنشاء (contentScale وcolorFilter). يمكنك أيضًا تطبيق Modifiers الحالي لتطبيق تأثيرات مختلفة على Image. يمكن استخدام المعدِّلات على أي Composable، وليس فقط على العنصر القابل للإنشاء 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.Fit portrait ContentScale.Fit landscape
ContentScale.Crop: اقتصاص الصورة من الوسط لتناسب المساحة المتاحة ContentScale.Crop portrait ContentScale.Crop landscape
ContentScale.FillHeight: تغيير حجم المصدر مع الحفاظ على نسبة العرض إلى الارتفاع لكي تتطابق الحدود مع ارتفاع الوجهة ContentScale.FillHeight portrait ‫ContentScale.FillHeight في الوضع الأفقي
ContentScale.FillWidth: تغيير حجم المصدر مع الحفاظ على نسبة العرض إلى الارتفاع لكي تتطابق الحدود مع عرض الوجهة ContentScale.FillWidth portrait ContentScale.FillWidth في الوضع الأفقي
ContentScale.FillBounds: لتغيير حجم المحتوى عموديًا وأفقيًا بشكل غير منتظم لملء حدود الوجهة (ملاحظة: سيؤدي ذلك إلى تشويه الصور إذا وضعتها في حاويات لا تتطابق مع نسبة العرض إلى الارتفاع الدقيقة للصورة) ContentScale.FillBounds portrait ContentScale.FillBounds landscape
ContentScale.Inside: لتغيير حجم المصدر للحفاظ على نسبة العرض إلى الارتفاع داخل حدود الوجهة إذا كان المصدر أصغر من الوجهة أو يساويها في كلا البُعدين، سيتصرف بشكل مشابه للقيمة `None`. سيتم دائمًا احتواء المحتوى ضمن الحدود. إذا كان المحتوى أصغر من الحدود، لن يتم تطبيق أي تغيير في الحجم. حجم صورة المصدر أكبر من الحدود: ContentScale.Inside portrait, source image larger than bounds حجم صورة المصدر أصغر من الحدود: ContentScale.Inside portrait, source image smaller than bounds حجم صورة المصدر أكبر من الحدود: ContentScale.Inside landscape, source image larger than bounds حجم صورة المصدر أصغر من الحدود: ContentScale.Inside landscape, source image smaller than bounds
ContentScale.None: عدم تطبيق أي تغيير في الحجم على المصدر إذا كان المحتوى أصغر من حدود الوجهة، لن يتم تكبيره ليناسب المساحة. حجم صورة المصدر أكبر من الحدود: ContentScale.None صورة عمودية، صورة المصدر أكبر من الحدود حجم صورة المصدر أصغر من الحدود: ‫ContentScale.None في الوضع العمودي، صورة المصدر أصغر من الحدود حجم صورة المصدر أكبر من الحدود: ContentScale.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)
)

قص صورة باستخدام 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))
)

قص صورة باستخدام RoundedCornerShape
الشكل 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)
)

استخدام Modifier.aspectRatio(16f/9f) على Image
الشكل 6: استخدام Modifier.aspectRatio(16f/9f) على صورة

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

يحتوي العنصر 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)
)

تم تطبيق ColorFilter.tint باستخدام BlendMode.SrcIn
الشكل 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
الشكل 8: اللون الأخضر مع 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) })
)

مصفوفة الألوان مع تشبُّع 0 (صورة بالأبيض والأسود)
الشكل 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))
)

تم تعديل سطوع الصورة وتباينها باستخدام 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))
        )
)

‫BlurEffect applied to image
الشكل 12: تطبيق BlurEffect على الصورة

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

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

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))
)

BlurEdgeTreatment.Unbounded
الشكل 13: BlurEdgeTreatment.Unbounded