تخصيص صورة

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

نطاق المحتوى

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

في المثال أدناه، يقتصر حجم عنصر "صورة مركبة" على 150dp مع حدود، ويتم ضبط الخلفية على اللون الأصفر في عنصر "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 أفقي
ContentScale.Crop: اقتصاص الصورة في منتصف المساحة المتوفّرة ContentScale.Crop portrait ContentScale.Crop landscape
ContentScale.FillHeight: تغيير حجم المصدر مع الحفاظ على نسبة العرض إلى الارتفاع لكي تتطابق الحدود مع ارتفاع الوجهة ContentScale.FillHeight portrait مقياس ContentScale.FillHeight أفقي
ContentScale.FillWidth: تغيير حجم المصدر مع الحفاظ على نسبة العرض إلى الارتفاع لكي تتطابق الحدود مع عرض الوجهة ContentScale.FillWidth portrait أفقي لـ ContentScale.Fillالعرض
ContentScale.FillBounds: يمكنك تغيير حجم المحتوى عموديًا وأفقيًا بشكل غير متساوٍ لملء حدود الوجهة. (ملاحظة: سيؤدي ذلك إلى تشويه الصور في حال وضعها في حاويات لا تتطابق مع نسبة العرض إلى الارتفاع الدقيقة للصورة) ContentScale.FillBounds portrait ContentScale.FillBounds أفقي
ContentScale.Inside: يمكنك تكبير/تصغير المصدر للحفاظ على نسبة العرض إلى الارتفاع داخل حدود الوجهة. إذا كان المصدر أصغر من الوجهة أو يساويها في كلتا السمتَين، سيعمل بالطريقة نفسها التي يعمل بها None. وسيظل المحتوى محصورًا في الحدود في جميع الأوقات. إذا كان المحتوى أصغر من الحدود، لن يتم تطبيق أيّ تكبير أو تصغير. الصورة المصدر أكبر من الحدود: ContentScale.Inside portrait, source image larger than bounds الصورة المصدر أصغر من الحدود: ContentScale.داخل عمودي، صورة المصدر أصغر من الحدود الصورة المصدر أكبر من الحدود: ContentScale.Inside landscape, source image larger than bounds الصورة المصدر أصغر من الحدود: ContentScale.Inside landscape, source image smaller than bounds
ContentScale.None: لا تطبِّق أيّ تغيير على حجم المصدر. إذا كان المحتوى أصغر من حدود الوجهة، لن يتم توسيعه ليلائم المنطقة. الصورة المصدر أكبر من الحدود: ContentScale.None عمودي، الصورة المصدر أكبر من الحدود الصورة المصدر أصغر من الحدود: ContentScale.بدون عمودي، الصورة المصدر أصغر من الحدود الصورة المصدر أكبر من الحدود: مقياس ContentScale.غير أفقي، الصورة المصدر أكبر من الحدود الصورة المصدر أصغر من الحدود: 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 ل dibujar un borde degradado de arco iris alrededor de la imagen:

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) على الصورة

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

تحتوي ميزة "الصورة القابلة للتركيب" على مَعلمة 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: Color.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) })
)

مصفوفة الألوان بتشبع 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 على الصورة
الشكل 12: تطبيق تأثير التمويه على الصورة

عند تمويه 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