自訂圖片

您可以使用 Image 可組合項 (contentScalecolorFilter) 中的屬性來自訂圖片。您也可以使用現有的修飾符Image 上來套用不同的效果。修飾符可用於任何可組合項,而不只在於 Image 可組合項,而 contentScalecolorFilter 則是 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. 在 Image 上使用 Modifier.aspectRatio(16f/9f)

色彩濾鏡:轉換圖片的像素顏色

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 的結果會產生不同的效果。例如,在圖片上使用 Color.Green 設定 BlendMode.Darken 會產生以下結果:

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(),並提供 radiusXradiusY 來分別指定水平和垂直方向的模糊半徑。

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