سفارشی‌سازی کردن تصویر

می‌توانید تصاویر را بااستفاده از دارایی‌های Image ترکیب‌شدنی (contentScale، colorFilter) سفارشی‌سازی کنید. همچنین می‌توانید اصلاح‌کننده‌های موجود را برای اعمال جلوه‌های مختلف روی Image اعمال کنید. از اصلاح‌کننده‌ها می‌توان در هر ترکیب‌شدنی استفاده کرد، نه فقط در ترکیب‌شدنی Image، درحالی‌که contentScale و colorFilter پارامترهای صریح در ترکیب‌شدنی Image هستند.

مقیاس محتوا

گزینه contentScale را برای برش دادن یا تغییر دادن نحوه مقیاس‌بندی تصویر در محدوده‌های آن مشخص کنید. به‌طور پیش‌فرض، اگر گزینه contentScale را مشخص نکنید، از ContentScale.Fit استفاده می‌شود.

در مثال زیر، عنصر ترکیبی Image به اندازه ۱۵۰dp با حاشیه محدود شده است، و پس‌زمینه در عنصر ترکیبی 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)
)

تصویر سگی که در دایره‌ای کامل چیده شده است.
شکل ۱. درحال برش تصویر با 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.

همچنین می‌توانید با گسترش دادن 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())
)

تصویر مربعی از سگی که در شکل بیضی سفارشی برش خورده است.
شکل ۳. برش تصویر با شکل مسیر سفارشی.

افزودن حاشیه به عنصر ترکیبی 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)
)

تصویر مربعی از سگی که به‌شکل دایره برش خورده است و حاشیه زردی دور شکل دایره‌ای دارد.
شکل ۴. تصویر بریده‌شده‌ای با حاشیه در اطراف آن.

برای ایجاد حاشیه گرادیان، می‌توانید از API 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)
)

تصویری دایره‌ای از سگی با حاشیه گرادیان رنگین‌کمانی در اطراف شکل دایره‌ای.
شکل ۵. حاشیه دایره‌ای با گرادیان رنگین‌کمان.

تنظیم نسبت ابعادی سفارشی

برای تبدیل تصویر به نسبت ابعادی سفارشی، از 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.

فیلتر رنگ: رنگ‌های پیکسل تصویر را تغییر می‌دهد

عنصر ترکیبی 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 درخواست داد.

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 اعمال شده است و سایه‌های سبز تیره‌تری ایجاد کرده است.
شکل ۸. ‫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) })
)

سگی با فیلتر سیاه‌وسفید که تمام اشباع رنگ را حذف می‌کند.
شکل ۹. ماتریس رنگ با اشباع ۰ (تصویر سیاه‌وسفید).

تنظیم کنتراست یا روشنایی 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 تنظیم شد.

رنگ‌های عنصر ترکیبی 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))
)

سگی با رنگ‌های معکوس که جلوه‌ای شبیه نگاتیو نشان می‌دهد.
شکل ۱۱. رنگ‌های تصویر معکوس شد.

محو کردن عنصر ساختنی 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 روی تصویر اعمال شد.

هنگام محو کردن 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))
)

تصویری محو از یک سگ که محوی آن فراتر از مرزهای تصویر اصلی است و لبه‌ها را تار می‌کند.
شکل ۱۳. BlurEdgeTreatment.Unbounded.