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

אפשר להתאים אישית תמונות באמצעות מאפיינים ב-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 composable יש פרמטר 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.