تخصيص صورة

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

حجم المحتوى

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

في المثال أدناه، تقتصر الصورة القابلة للإنشاء على حجم 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 ContentScale.Fit أفقي
ContentScale.Crop: اقتصاص الصورة في منتصف المساحة المتوفّرة مقياس ContentScale.اقتصاص الصورة العمودية اقتصاص الصور الأفقية
ContentScale.FillHeight: يمكنك تغيير حجم المصدر مع الحفاظ على نسبة العرض إلى الارتفاع بحيث تتطابق الحدود مع ارتفاع الوجهة. مقياس ContentScale.FillHeight عمودي مقياس 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.Inside portrait, source image smaller than bounds الصورة المصدر أكبر من الحدود: ContentScale.داخل الأفقي، الصورة المصدر أكبر من الحدود الصورة المصدر أصغر من الحدود: ContentScale.داخل الأفقي، صورة المصدر أصغر من الحدود
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) في الصورة

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

تتضمن الصورة القابلة للإنشاء معلَمة 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))
)

PlayerEdgeTreatment.غير محدود
الشكل 13: BlurEdgeTreatment.Unbounded