はじめてのAndroidアプリ(画像編)

## はじめに
この記事は、Kotlinもアプリ開発も学びたての筆者が、実際に手を動かしながらアプリ開発を学んでいくものになります。
本記事は第2弾の位置づけで、[前回の記事](https://qiita.com/teyama3/items/352bdb34743a6713f732)では Android Studio のダウンロードから初期構築までをやりました。

今回は[このアプリ](https://github.com/google-developer-training/basic-android-kotlin-compose-training-dice-roller)を題材にアプリ開発に慣れていこうと思ったのですが…
ちょっと知識が足りないことに気付いたので、まずは画像の基礎を学びたいと思います。

## 対象読者
* Androidエンジニアを目指している方（自分は目指してます！）
* 素人の奮闘記を読みたい方

## アプリに画像を表示する
まず、ストレージに保存されている画像をアプリに表示するにはどうしたら良いのでしょうか。

### Android Studio に画像を配置する
とりあえず、画像をIDEに読み込ませることが必要です。

Android Studio の Project の下にある Resource Manager をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630401/5b0e68f9-269f-35d9-df6d-6bb19e1c91c8.png)

＋ > Import Drawables としてから、対象の画像を選択します。
今回は、この画像をアプリに表示してみたいと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630401/d12b4080-2e62-7cca-e64c-b774092a4e74.png)

QUALIFIER TYPE は `Density` を選択します。
この設定については勉強不足で、解釈が合っているか疑問ですが、
デバイスによって画面のサイズや密度が異なり、それによって解像度が違います。
そのため、**異なるデバイスでも一貫した見え方になるように設定する項目**のようです。

https://developer.android.com/training/multiscreen/screendensities?hl=ja

VALUE は `No Density` を選びます。
こちらは**1インチあたり何ピクセルの密度に最適化するのかということを設定する項目**のようです。
例えば`Midium Density`であれば、`160dpi`で一貫して見える画像として扱ってくれるのではないでしょうか。
ちなみに、`No Density` とすることで、後に作成される`drawable-nodpi`ディレクトリに画像を配置することで、デバイスに合わせて自動でサイズ変更を行わないという設定になるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630401/e73a2b03-3799-8721-2779-eea323d73b0a.png)

### Android Studio のディレクトリ構成
1つ前のセクションでも少し触れましたが、Android Studio に画像をインポートすると、以下のようなディレクトリが構築されています。

``` ディレクトリ構成
myfirstapp
　∟ app
 　　∟ src
   　　　∟ main
      　　　∟ res
         　　　∟ drawable
            　 ∟ drawable-nodpi
               ∟ ・
               ∟ ・
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630401/379da0ef-f48e-9ca4-4e28-c355cfdb8fe0.png)

このようにディレクトリごとに画像を分類することで、画面サイズごとに異なるUIを表示することができるようです。

### 画像を表示してみる
それでは、アプリ内に画像を表示してみたいと思います。
文字の場合は `Text` を使いましたが、画像の場合は `Image` を使って表示していきます。

```kotlin:MainActivity.kt
import androidx.compose.foundation.Image
import androidx.compose.ui.res.painterResource

～中略～

@Composable
fun GreetingImage(message: String, using: String, modifier: Modifier = Modifier) {
    val image = painterResource(id = R.drawable._06767)
    Image(
        painter = image
        contentDescription = null
    )
}

```
`painterResource`関数を使って`drawable-nodpi`ディレクトリに保存してある画像を読み込みます。

### なぜ`R.drawable`か
ここで一つ疑問が浮かびました。
画像の保存先は`drawable-nodpi`や`drawable-mdpi`など、様々なはずです。
なぜ`R.drawable`とするだけで、最適な画像を選んでくれるのでしょうか。

それは、Androidに一定の優先順位があるためなんだそうです。
例えば、以下のように同名の画像ファイルがあったとします。

``` ディレクトリ構成
myfirstapp
　∟ app
 　　∟ src
   　　　∟ main
      　　　∟ res
         　　　∟ drawable
            　 ∟ drawable-nodpi
            　　　∟ _06767.png
               ∟ drawable-mdpi
                　∟ _06767.png
               ∟ ・
```
もしデバイスの画面密度が `mdpi` の場合、`R.drawable._06767` と書くと、`drawable-mdpi` に保存されている `_06767.png` を優先してくれます。

そしてもし、`drawable-mdpi` に同名のファイルが無かったとしたら、そこで初めて `drawable-nodpi` が選択されるんだそうです。

リソースの優先度について

https://developer.android.com/guide/topics/resources/providing-resources?hl=ja#AlternativeResources

Imageコンポーザブルのドキュメントはこちら

https://developer.android.com/reference/kotlin/androidx/compose/foundation/package-summary

### contentDescription
Imageコンポーザブルには、`contentDescription` という引数があります。
画像が何らかの意味を持っている場合は、画像の説明を設定することで、`TalkBack` という機能で読み上げが行われます。
これは、視覚障害を持つ方がアプリのUIを理解するのに必要な機能です。

ただし今回は、画像自体に特別な意味を持たせる訳ではありませんので、`null` を設定して、`TalkBack` から無視されるようになります。

https://developer.android.com/develop/ui/compose/graphics/images/loading?hl=ja

### プレビュー
`@Preview` アノテーションを使って、プレビューしてみたいと思います。
```kotlin:MainActivity.kt
@Preview(showBackground = true)
@Composable
fun GreetingImagePreview() {
    HellomyappTheme {
        GreetingImage(
            message = "android app development",
            using = "using Kotlin"
        )
    }
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630401/aed77b1e-cc4b-9a20-bfde-0981ae31dc57.png)

## TextとImageを一緒に表示する
[前回の記事](https://qiita.com/teyama3/items/352bdb34743a6713f732)で作った `GreetingText` 関数と一緒に表示してみます。

```kotlin:MainActivity.kt
@Composable
fun GreetingImage(message: String, using: String, modifier: Modifier = Modifier) {
    val image = painterResource(id = R.drawable._06767)
    Image(
        painter = image,
        contentDescription = null
    )
    GreetingText(
        message = message,
        using = using
    )
}
```
こうすると、それぞれのコンポーザブルの位置を指定していないので、重なって表示されてしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630401/c704da31-7db7-4c0b-91ac-783efe707138.png)

そこで、`Column` コンポーザブルを利用して、縦に並べてみます。

```kotlin:MainActivity.kt
@Composable
fun GreetingImage(message: String, using: String, modifier: Modifier = Modifier) {
    val image = painterResource(id = R.drawable._06767)
    Column(
        modifier,
        verticalArrangement = Arrangement.Center
    ) {
        Image(
            painter = image,
            contentDescription = null
        )
        GreetingText(
            message = message,
            using = using
        )
    }
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630401/93fed559-b5b6-7f9e-a333-a0c6498db7de.png)

## 次回予定
今回はアプリに画像を表示するところを学びました。
次回こそ[このアプリ](https://github.com/google-developer-training/basic-android-kotlin-compose-training-dice-roller.git)を題材に学んでいこうと思います。