התאמה אישית של תמונה

אפשר להתאים אישית תמונות באמצעות מאפיינים ב-Image composable (contentScale, colorFilter). אפשר גם להחיל modifiers קיימים כדי להחיל אפקטים שונים על Image. אפשר להשתמש במאפייני שינוי בכל קומפוזבל, ולא רק בקומפוזבל Image, בעוד ש-contentScale ו-colorFilter הם פרמטרים מפורשים בקומפוזבל Image.

היקף התוכן

מציינים אפשרות contentScale לחיתוך או לשינוי של קנה המידה של התמונה בתוך הגבולות שלה. כברירת מחדל, אם לא מציינים contentScale אפשרות, נעשה שימוש ב-ContentScale.Fit.

בדוגמה הבאה, גודל הרכיב Image מוגבל ל-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.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 API כדי לצייר מסגרת עם מעבר צבעים של קשת מסביב לתמונה:

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.

הוספה של 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) })
)

כלב עם מסנן שחור לבן, ללא רוויית צבע.
איור 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.