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

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

קנה המידה של התוכן

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

בדוגמה הבאה, ה-composable של התמונה מוגבל לגודל 150dp עם שוליים, והרקע מוגדר לצהוב ב-composable של 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 landscape
ContentScale.Crop: חיתוך התמונה למרכז התמונה לשטח הזמין. ContentScale.Crop portrait ContentScale.Crop landscape
ContentScale.FillHeight: שינוי קנה המידה של המקור תוך שמירה על יחס הגובה-רוחב, כך שהגבולות יהיו תואמים לגובה היעד. לאורך של ContentScale.FillHeight ContentScale.FillHeight לרוחב
ContentScale.FillWidth: שינוי קנה המידה של המקור תוך שמירה על יחס הגובה-רוחב, כך שהגבולות יהיו תואמים לרוחב היעד. ContentScale.FillWidth portrait ContentScale.FillWidth לרוחב
ContentScale.FillBounds: שינוי קנה המידה של התוכן באופן לא אחיד אנכית ואופקית כדי למלא את גבולות היעד. (הערה: הפעולה הזו גורמת לעיוות של תמונות אם מניחים אותן בקונטיינרים שלא תואמים ליחס המדויק של התמונה) ContentScale.FillBounds לאורך ContentScale.FillBounds לרוחב
ContentScale.Inside: שינוי קנה המידה של המקור כדי לשמור על יחס הגובה-רוחב בתוך גבולות היעד. אם המקור קטן מהיעד או שווה לו בשני המאפיינים, הוא מתנהג באופן דומה ל-'None'. התוכן תמיד יהיה בתוך הגבולות. אם התוכן קטן מהגבולות, לא תחול הגדלה. תמונת המקור גדולה מהגבולות: ContentScale.Inside portrait, source image larger than bounds תמונת המקור קטנה מהגבולות: ContentScale.Inside portrait, source image smaller than bounds תמונת המקור גדולה מהגבולות: ContentScale.Inside landscape, source image larger than bounds תמונת המקור קטנה מהגבולות: ContentScale.Inside landscape, source image smaller than bounds
ContentScale.None: לא מחילים שינוי קנה מידה על המקור. אם התוכן קטן מהגבולות של היעד, הוא לא ישופר כדי להתאים לאזור. תמונת המקור גדולה מהגבולות: ContentScale.ללא לאורך, תמונת מקור גדולה מהגבולות תמונת המקור קטנה מהגבולות: ContentScale.None portrait, source image smaller than bounds תמונת המקור גדולה מהגבולות: 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: חיתוך תמונה והוספת גבול מסביבה

אם רוצים ליצור מסגרת עם שינוי הדרגתי, אפשר להשתמש ב-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)
)

גבול עיגול עם הדרגתיות של צבעי הקשת
איור 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) בתמונה

מסנן צבעים – שינוי צבעי הפיקסלים של התמונה

ל-Image composable יש פרמטר colorFilter שיכול לשנות את הפלט של פיקסלים ספציפיים בתמונה.

כוונון של תמונה

שימוש ב-ColorFilter.tint(color, blendMode) יגרום להחלה של שילוב צבעים עם הצבע הנתון על ה-composable של 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)
)

גוון Color.Green עם BlendMode.Darken
איור 8: גוון צבע ירוק עם 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: החלת 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