画像をカスタマイズする

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

画像は、Image コンポーザブル(contentScalecolorFilter)のプロパティを使用してカスタマイズできます。既存の Modifiers を利用して、Image にさまざまな効果を適用することもできます。修飾子は、Image コンポーザブルだけでなく、任意のコンポーザブルに使用できます。一方、contentScalecolorFilter は、Image コンポーザブルの明示的なパラメータです。

コンテンツの調整

contentScale オプションを指定することで、画像を切り抜いたり、境界内で画像の大きさを変更したりできます。contentScale オプションが指定されていない場合、デフォルトでは ContentScale.Fit が使用されます。

以下の例では、下の表の異なる ContentScale オプションを示すために、Image コンポーザブルの枠を 150 dp に制限し、Image コンポーザブルの背景を黄色に設定しています。

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 横長
ContentScale.Crop: 空いているスペースがなくなるように画像を切り抜いて中央に配置します。 ContentScale.Crop 縦長 ContentScale.Crop 横長
ContentScale.FillHeight: 境界がデスティネーションの高さと一致するように、アスペクト比を維持しながら元の画像を拡大・縮小します。 ContentScale.FillHeight 縦長 ContentScale.FillHeight 横長
ContentScale.FillWidth: 境界がデスティネーションの幅と一致するように、アスペクト比を維持しながら元の画像を拡大・縮小します。 ContentScale.FillWidth 縦長 ContentScale.FillWidth 横長
ContentScale.FillBounds: デスティネーションの境界に合うように、垂直方向と水平方向に不均一にコンテンツを拡大・縮小します(注: 画像の比率に正確に合っていないコンテナに配置すると、画像が歪みます)。 ContentScale.FillBounds 縦長 ContentScale.FillBounds 横長
ContentScale.Inside: デスティネーションの境界内でアスペクト比を維持するように元の画像を拡大・縮小します。元の画像の縦と横がデスティネーションと同じか小さい場合は、「None」と同じような結果になり、コンテンツは常に境界内に収まります。コンテンツが境界よりも小さい場合、スケーリングは適用されません。 元の画像が境界より大きい: ContentScale.Inside 縦長、元の画像が境界より大きい 元の画像が境界より小さい: ContentScale.Inside 縦長、元の画像が境界より小さい 元の画像が境界より大きい: ContentScale.Inside 横長、元の画像が境界より大きい 元の画像が境界より小さい: ContentScale.Inside 横長、元の画像が境界より小さい
ContentScale.None: 元の画像にスケーリングを適用しません。コンテンツがデスティネーションの境界より小さくても、境界に合うように拡大はされません。 元の画像が境界より大きい: ContentScale.None 縦長、元の画像が境界より大きい 元の画像が境界より小さい: ContentScale.None 縦長、元の画像が境界より小さい 元の画像が境界より大きい: 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 = "Golden retriever in falling autumn leaves",
    contentScale = ContentScale.Crop,
    modifier = Modifier.size(200.dp).clip(SquashedOval())
)
シェイプのカスタム path を指定して画像をクリッピング
図 3: シェイプのカスタム path を指定して画像をクリッピング

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)
)
画像に Modifier.aspectRatio(16f/9f) を適用する
図 6: 画像に Modifier.aspectRatio(16f/9f) を適用する

カラーフィルタ - 画像のピクセルカラーを変換する

Image コンポーザブルには、画像の各ピクセルの出力を変更できる colorFilter パラメータが用意されています。

画像の色合いを調整する

ColorFilter.tint(color, blendMode) を使用すると、指定された色のブレンドモードが Image コンポーザブルに適用されます。ColorFilter.tint(color, blendMode) は、BlendMode.SrcIn を使用してコンテンツの色合いを調整します。つまり、画像が表示される画面が、指定した色になります。これは、異なるテーマを設定する必要があるアイコンやベクターに役立ちます。

Image(
    painter = painterResource(id = R.drawable.ic_bus_24),
    contentDescription = stringResource(id = R.string.bus_schedule_content_desc),
    colorFilter = ColorFilter.tint(Color.Yellow)
)
BlendMode.SrcIn を指定して ColorFilter.tint を適用
図 7: BlendMode.SrcIn を指定して ColorFilter.tint を適用

他の BlendMode の結果は異なります。たとえば、画像に BlendMode.DarkenColor.Greenを設定すると、次のような結果になります。

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_desc),
    colorFilter = ColorFilter.tint(Color.Green, blendMode = BlendMode.Darken)
)
BlendMode.Darken を指定した場合の Color.Green での色合い調整
図 8: BlendMode.Darken を指定した場合の Color.Green での色合い調整

利用可能な各種 BlendMode の詳細については、BlendMode のリファレンス ドキュメントをご覧ください。

カラー マトリックスを使用して画像にフィルタを適用する

カラー マトリックス ColorFilter オプションを使用して画像を変換します。たとえば、画像にモノクロ フィルタを適用するには、ColorMatrix を使用して、彩度を 0f に設定します。

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_desc),
    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_desc),
    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_desc),
    colorFilter = ColorFilter.colorMatrix(ColorMatrix(colorMatrix))
)
色を反転させた画像
図 11: 色を反転させた画像

Image コンポーザブルをぼかす

画像をぼかすには、Modifier.blur() を使用します。radiusXradiusY を指定して、ぼかす範囲の半径を水平方向と垂直方向のそれぞれで指定します。

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_desc),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(150.dp)
        .blur(
             radiusX = 10.dp,
             radiusY = 10.dp,
             edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(8.dp))
         )
)
画像にぼかし効果を適用
図 12: 画像にぼかし効果を適用

Images をぼかす場合は、BlurredEdgeTreatment.Unbounded ではなく BlurredEdgeTreatment(Shape) を使用することをおすすめします。後者は、元のコンテンツの境界を超えてレンダリングする画像にぼかしを入れる場合に使用します。画像の場合、コンテンツの境界外にレンダリングすることは少ないかもしれませんが、角丸の長方形をぼかす際には、両者を区別することが必要になる場合があります。

たとえば、上記の画像で BlurredEdgeTreatment を Unbounded に設定すると、画像の境界がはっきりせずにぼやけて表示されます。

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_desc),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(150.dp)
        .blur(
             radiusX = 10.dp,
             radiusY = 10.dp,
             edgeTreatment = BlurredEdgeTreatment.Unbounded
         )
         .clip(RoundedCornerShape(8.dp))
)
BlurEdgeTreatment.Unbound
図 13: BlurEdgeTreatment.Unbounded