Jetpack Compose入門(9) 画像を表示する



前回まではTextコンポーネントを使って文字列を表示してきました。文字がある程度自由に表示できるようになってきたところで、今回はJetpack Composeで画像を表示する方法について確認してきましょう。

Imageコンポーネント

Jetpack Composeで画像を表示するには、Imageコンポーネントを使います。Imageandroidx.compose.foundationパッケージに定義されています。TextをはじめとしたUIウィジェットがmaterialパッケージに定義されているのに対し、「画像を表示する」という機能はmaterialパッケージから切り離されているのが、設計として興味深いです。デザインが進化するとmaterialパッケージは連動して変化していきますが、画像の表示という基本的な機能はデザインのトレンドとは独立して存在しているということですね。

さて、とりあえず画像を表示するための最もシンプルなコードはこんな感じです。

Image(
    painter = painterResource(R.drawable.dog),
    contentDescription = "A dog image"
)

画像リソースの準備

まずは表示する画像を用意しましょう。画像ファイルをdrawableフォルダに置きます。アイコンなどの場合、きちんとやるなら、いくつかの解像度を用意して、それぞれフォルダを分けて・・・といった作業をしますが、とりあえず表示するだけなら、一番簡単なのは画像ファイルをAndroid StudioのProjectウィンドウのdrawableフォルダにドラッグ&ドロップする方法です。

Image()の定義と引数の設定

Imageコンポーザブル関数は4つ定義されています。(2021年10月時点。うち一つは早くもDeprecatedになっています)このうち今回使うのは下記の関数です。引数のうち必須のものはpaintercontentDescriptionの2つで、上の例でもこの2つだけを設定しています。

@Composable
fun Image(
    painter: Painter?,
    contentDescription: String?,
    modifier: Modifier? = Modifier,
    alignment: Alignment? = Alignment.Center,
    contentScale: ContentScale? = ContentScale.Fit,
    alpha: Float? = DefaultAlpha,
    colorFilter: ColorFilter? = null
): Unit

Painterクラスってのがいきなり出てきて、何!?という感じですね。Painterクラスはandroidx.compose.ui.graphics.painterパッケージに定義されている、画像として描画するものを表す抽象クラスです。BitmapPainterなどの実装が用意されていますが、これらを直接使う機会はそれほど多くなくて、さまざまな用途に合わせてPainterクラスオブジェクトを作成する関数が用意されているので、だいたいはそちらを使います。上の例ではpainterResource()という関数を使っています。プロジェクトの画像リソースからPainterオブジェクトを作成する関数で、androidx.compose.ui.resパッケージに定義されています。(探しにくい!) 引数にはdrawableのIDを渡します。

@Composable
fun painterResource(id: @DrawableRes Int?): Painter

contentDescriptionは、画像の内容を説明する文字列で、視覚障がい者向けの説明などに使われます。nullを指定することもできますが、Storeで公開するアプリの場合はなるべく具体的な説明を入れておいた方がよいでしょう。

ContentScale

Image()の引数のうち、よく使うものを一つ試してみましょう。contentScale引数は、画像のサイズと表示エリアのサイズが異なる場合に、画像をどのように表示するのかを指定します。以下の例では、違いが分かりやすいようにmodifier引数も指定して枠線を表示しています。modifierについては詳しくは前回の「コンポーネントを装飾する」を参照して下さい。

Fit

Image(
    painter = painterResource(R.drawable.dog),
    contentDescription = "A dog image",
    modifier = Modifier.border(1.dp, Color.Black),
    contentScale = ContentScale.Fit
)

ContentScale.Fitは、contentScale引数のデフォルト値です。この値を指定すると、画像の縦横比を維持したまま、画像全体が表示エリアに収まるように拡大・縮小します。画像全体を表示するときによく使います。

Crop

Image(
    painter = painterResource(R.drawable.dog),
    contentDescription = "A dog image",
    modifier = Modifier.border(1.dp, Color.Black),
    contentScale = ContentScale.Crop
)

ContentScale.Cropを指定すると、画像の縦横比を維持したまま、表示エリア全体を埋めるように画像を表示します。フォトギャラリーのサムネイル表示などでよく使われます。

None

Image(
    painter = painterResource(R.drawable.dog),
    contentDescription = "A dog image",
    modifier = Modifier.border(1.dp, Color.Black),
    contentScale = ContentScale.None
)

ContentScale.Nonteを指定すると、画像の拡大縮小は行いません。この例では表示エリアより画像の方が小さいので、余白ができています。逆に画像の方が大きければ、画像の周囲が切り取られて表示されます。

FillBounds

Image(
    painter = painterResource(R.drawable.dog),
    contentDescription = "A dog image",
    modifier = Modifier.border(1.dp, Color.Black),
    contentScale = ContentScale.FillBounds
)

ContentScale.FillBoundsを指定すると、画像の高さと幅を表示エリアの高さと幅に合わせて拡大・縮小します。画像の縦横比は維持されません。

ほかにもいくつかのオプションがありますが、よく使うのはこの4つだと思います。

まとめ(と補足)

今回はImageコンポーネントを使って画像を表示する方法を確認しました。Textコンポーネントと同様よく使うコンポーネントですので、使い方を覚えましょう。

また実際のアプリでは、Webから取得した画像を表示したり、デバイスのストレージに保存されている画像を表示したりするケースも多いと思います。そのようなケースには、Coilライブラリを使うと対応できます。ライブラリの使い方については、基本編終了後の実践編で紹介するつもりです。