Jetpack Compose をさわってみた

専門学生時代はAndroid開発にすごくハマっていて、平日でも寝るのを忘れてコーディングするぐらい開発にのめり込んでいたのですが、
それももう5年ほど前で、社会人になってからは客先常駐で組み込みエンジニアとしてC言語で開発をやっています。

先日、ふと「あ、こういうアプリを作りたいな」と思い付き、
「よし、久しぶりにAndroidアプリを開発しよう」と思いAndroidStudioを立ち上げたのですが、

うん、なるほど。わからん。
さすがに5年も離れていると、いろいろと変わってるし、忘れてるし。

さて、どうしようか。と考えていたところ`JetpackCompose`という文字を発見。

[公式ドキュメント](https://developer.android.com/jetpack/compose?hl=ja)を見てみると、

> Jetpack Compose は、ネイティブ UI をビルドする際に推奨される Android の最新ツールキットです。Android での UI 開発を簡素化し、加速します。少ないコード、パワフルなツール、直感的な Kotlin API を使用してアプリをすぐに動かすことができます。

ふむふむ、「どうせほぼ最初から勉強し直すなら新しいことをやってみるか」ということで、JetpackComposeを触ってみることにしました。

ということで、とりあえずチュートリアルをちょっと触ってみたので、自分が後で見返したりする用に書いてみようと思います。

## アノテーション
### `@Composable`

* Jetpack Compose は、コンポーズ可能な関数に基づいて構築される。
* コンポーズ可能な関数を使用すると、UI の外観とデータの依存関係を指定することにより、アプリの UI をプログラムで定義できる。
* コンポーズ可能な関数は、関数名に `@Composable` アノテーションを追加するだけで作成できる。

Compose UI ライブラリで定義されているコンポーズ可能な関数（`Text`, `Image`, `Spacer`など）も使用できます。

### `@Preview`
* Android Studio 内でコンポーズ可能な関数をプレビューできる。
* `@Composable`の前に`@Preview`アノテーションを追加する。


## レイアウト

* `Column`関数で、要素を垂直方向に揃える。
* `Row`関数で、アイテムを水平方向に揃える。
* `Box`関数で、要素を積み重ねる。
* `modifier`パラメータで、`size`や`padding`を指定できる。

### `modifier`

その名の通り、要素を修飾（`padding`や`size`, `clickable`など）し、以下のようなことができる。

* コンポーザブルのサイズ、レイアウト、動作、外観を変更する
* ユーザー補助ラベルなどの情報を追加する
* ユーザー入力を処理する
* 要素をクリック可能、スクロール可能、ドラッグ可能、ズーム可能にするなど、高レベルの操作を追加する

詳しくは → [Modifier](https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier)
#### ないとき
``` MainActivity.kt
data class Message(val author: String, val body: String)

@Composable
fun MessageCard(msg: Message){
    Row() {
        Image(
            painter = painterResource(id = R.drawable.icon),
            contentDescription = "Contact profile picture"
        )
        Column{
            Text(text = msg.author)
            Text(text = msg.body)
        }
    }
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213802/721bac38-e08b-dc75-0cb7-20fc5131a461.png)

#### あるとき
``` MainActivity.kt
data class Message(val author: String, val body: String)

@Composable
fun MessageCard(msg: Message){
    // Add padding around our message
    Row(modifier = Modifier.padding(all = 8.dp)) {
        Image(
            painter = painterResource(id = R.drawable.icon),
            contentDescription = "Contact profile picture",
            modifier = Modifier
                // Set image size to 50 dp
                .size(50.dp)
                // Clip image to be shaped as a circle
                .clip(CircleShape),
            // ContentScale to be scales the source uniformly
            contentScale = ContentScale.Crop
        )

        // Add a horizontal space between the image and the column
        Spacer(modifier = Modifier.width(8.dp))

        Column{
            Text(text = msg.author)
            // Add a vertical space between the author and message texts
            Spacer(modifier = Modifier.height(4.dp))
            Text(text = msg.body)
        }
    }
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213802/b93fafe9-31e7-2b67-5129-fa1feab6e019.png)

### マテリアルデザインを使用する
マテリアルデザインは、Googleが提唱したデザインのこと
→ [Material Design](https://m3.material.io/)

アプリのテーマで定義されているとおりにスタイルを継承し、アプリ内での一貫性を確保するために、プロジェクト内で作成されたマテリアル テーマ `プロジェクト名Theme` と `Surface` を使用して、`MessageCard` 関数をラップします。

``` MainActivity.kt
setContent {
    JetpackComposeTutorialTheme {
        // A surface container using the 'background' color from the theme
        Surface(
            modifier = Modifier.fillMaxSize(),
            color = MaterialTheme.colorScheme.background
        ) {
            MessageCard(msg = Message("Colleague", "Hey, take a look at Jetpack Compose, it's great!"))
    }
}
```

#### Color
[Material Design 3 in Compose - Color scheme](https://developer.android.com/jetpack/compose/designsystems/material3#color-scheme)

`MaterialTheme.colors`を使用して、ラップされたテーマの色でスタイルを設定する。
``` .kt
MaterialTheme.colorScheme.secondary
```

#### Typography
[Material Design 3 in Compose - Typography](https://developer.android.com/jetpack/compose/designsystems/material3#typography)

`MaterialTheme.typography`を使用して、スタイルを設定する。
``` .kt
MaterialTheme.typography.titleLarge
```

#### Shape
[Material Design 3 in Compose - Shapes](https://developer.android.com/jetpack/compose/designsystems/material3#shapes)

`MaterialTheme.shapes`を使用して、形状を設定する。
``` .kt
MaterialTheme.shapes.medium
```

#### ダークモードとライトモード
ダークモードとライトモードをプレビューで確認することが出来ます。
``` .kt
@Preview(name = "Light Mode")
@Preview(
    uiMode = Configuration.UI_MODE_NIGHT_YES,
    showBackground = true,
    name = "Dark Mode"
)
```
実機で動かさなくても確認できるのはいいなと思いました。
それぞれで使用されるカラーは、`ui.theme/Theme.kt`, `ui.theme/Color.kt`で確認出来ます。


## Now in Android
というサンプルアプリがあるみたいです。(GooglePlayストアでアプリが公開されています。)

[GitHubのリポジトリ](https://github.com/android/nowinandroid)より

> Now in Android is a fully functional Android app built entirely with Kotlin and Jetpack Compose. It follows Android design and development best practices and is intended to be a useful reference for developers. As a running app, it's intended to help developers keep up-to-date with the world of Android development by providing regular news updates.

Now in Androidは、Androidの設計と開発のベストプラクティスに沿って、KotlinとJetpackComposeで作られていて、開発者にとって有用なリファレンスとなることを目的にしているそうです。

ドキュメントも
- アーキテクチャに関する [architecture learning journey](https://github.com/corleonyis/nowinandroid/blob/main/docs/ArchitectureLearningJourney.md)
- モジュール化に関する [modularization learning journey](https://github.com/corleonyis/nowinandroid/blob/main/docs/ModularizationLearningJourney.md)

があり、デザイン事例 [design case study](https://www.figma.com/community/file/1164313362327941158) もあるので、JetpackComposeの基本が分かったらNow in Androidで勉強してみようと思います。

## 感想
とりあえず、さらっと書いてみました。
`Image`に
``` .kt
modifier = Modifier.size(50.dp).clip(CircleShape)
```
を付け足すだけで、よくアイコンとかで使う感じのが出来て、
ちょっと触ってみた感じ、確かにコード量も少なくなりそうだし、開発スピードも上がりそうな感じがします。

今後もJetpackComposeを使っていって、何かあれば追記か、別で記事書こうかなと思います。