🫠

Jetpack Composeの概要を公式ドキュメントで知る!

に公開

はじめに

現在、Webアプリを中心に開発していますが、今後はスマホアプリにも挑戦したいと思っています。
その中で、Jetpack Composeが今後のAndroidアプリ開発の主流になると聞き、公式にも推奨されていることから学び始めました。
この記事では、Jetpack Composeチュートリアルサイトを参考にして、Jetpack Composeの概要を理解していこうと思います。


🚀 Jetpack Composeとは?

  • Androidの最新UIツールキット
  • 宣言的UI(XMLではなくKotlinコードでUIを記述)
  • メリット
    • コード量が少なくなる
    • リアルタイムプレビュー可能
    • ステート管理がシンプル
    • 既存のViewとも共存できる

🏗️ 基本構成

MainActivity.kt
@Composable
fun Greeting(name: String) {
    Text(text = "Sorry $name!")
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    Greeting("Android")
}

詳細

  • @Composable:UI部品として扱う関数を示すアノテーション
    ※アノテーション:コードに特別な意味を与えるマークのこと。
     @Composableは「これはUIを構築する関数です」とComposeに伝えるマーク。
     @Previewは「このComposableをプレビュー表示したい」とIDEに伝えるマーク。

  • TextなどのUI部品をKotlinで直接記述

  • @Preview:プレビュー表示用

今回はプロジェクトを作成したデフォルトのコードです。
@Composableではテキストを表示する関数Greetingを定義し、
@Previewでは関数Greetingを発火する関数GreetingPreviewを定義しています。

これだけではただの定義ですが、@Composableと**@Preview**のおかげで発火するべき関数を認識してくれます。
このおかげでGreetingPreview関数を発火してテキスト表示ができる!という理由なんですね~。

プレビュー結果はこちら

![]

Sorry Androidを出力してみました

🖼 レイアウト

基本構成では、テキストをプレビュー表示しました。
ここからは、プロフィール形式に画像とテキストを横並びに
しようと思います。

テキストの表示

まずは、テキストを表示させていきます。

このままでは重なっていて何を書いているかわからないので、一つずつ**Text()**を表示できるようにします。

MainActivity.kt
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MessageCard(Message("Android", "Jetpack Compose"))
        }
    }
}

data class Message(val author: String, val body: String)

@Composable
fun MessageCard(msg: Message) {
    Text(text = msg.author)
    Text(text = msg.body)
}

@Preview
@Composable
fun PreviewMessageCard() {
    MessageCard(
        msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!")
    )
}

これでテキスト表示ができました!

次に、画像の表示をしていきます。
まずは、画像をこのプロジェクトにインポートします。

インポート方法はこちら

Resourse Managerタブに移動します。
「+」→「Import Drawables」から使用したい画像をインポートしてください

無事画像をインポートできたので、プレビュー表示をさせていきます。

画像はテキストの左に表示させていきます。

これで、画像の表示ができました!

最後に画像とテキストに画像の整形と余白を持たせてみました。
結果がこちらです。見やすくなりましたね。

コードはこちら
MainActivity.kt
@Composable
fun Greeting(msg: Message) {
    // Add padding around our greeting
    Row(modifier = Modifier.padding(all = 8.dp)) {
        Image(
            painter = painterResource(R.drawable.img0),
            contentDescription = "Contact Profile Picture",
            modifier = Modifier
                // Set image size to 40 dp
                .size(40.dp)
                // Clip image to be shaped as a circle
                .clip(CircleShape)
        )

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

        Column {
            Text(text = "Sorry ${msg.author}!")
            // Add a vertical space between the author and the body
            Spacer(modifier = Modifier.height(4.dp))
            Text(text = msg.body)
        }
    }
}

🧱 マテリアルデザイン

前回の章では、メッセージカードのレイアウトを作成していきました。
今回はシンプルなレイアウトからデザインを設定して外観の改良をしていきます!

🖌 文字色の変更

@Composable
fun Greeting(msg: Message) {
    // Add padding around our greeting
    Row(modifier = Modifier.padding(all = 8.dp)) {
        Image(
            painter = painterResource(R.drawable.img0),
            contentDescription = "Contact Profile Picture",
            modifier = Modifier
                // Set image size to 40 dp
                .size(40.dp)
                // Clip image to be shaped as a circle
                .clip(CircleShape)
                // Set border around image
                .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
        )

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

        Column {
            Text(
                text = "Sorry ${msg.author}!",
                // Set color to secondary
                color = MaterialTheme.colorScheme.secondary
                )
            // Add a vertical space between the author and the body
            Spacer(modifier = Modifier.height(4.dp))
            Text(text = msg.body)
        }
    }
}

🧱 タイポグラフィー

タイポグラフィーとは...
  文字(フォント)の形、サイズ、配置、行間などを整えて、読みやすく・美しくする技術のこと。

今回は文字サイズとフォントを変更しています。

Column {
            Text(
                text = "Sorry ${msg.author}!",
                // Set color to secondary
                color = MaterialTheme.colorScheme.secondary,
                // Set font-size and font-family to titleSmall
                style = MaterialTheme.typography.titleSmall,
                )
            // Add a vertical space between the author and the body
            Spacer(modifier = Modifier.height(4.dp))
            Text(
                text = msg.body,
                // Set font-style to bodyMedium
                style = MaterialTheme.typography.bodyMedium,
                )
        }

形状の変更

最後に、メッセージ本文に変更を加えます。

@Composable
fun MessageCard(msg: Message) {
   Row(modifier = Modifier.padding(all = 8.dp)) {
       Image(
           painter = painterResource(R.drawable.profile_picture),
           contentDescription = null,
           modifier = Modifier
               .size(40.dp)
               .clip(CircleShape)
               .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
       )
       Spacer(modifier = Modifier.width(8.dp))

       Column {
           Text(
               text = msg.author,
               color = MaterialTheme.colorScheme.secondary,
               style = MaterialTheme.typography.titleSmall
           )

           Spacer(modifier = Modifier.height(4.dp))

           Surface(shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp) {
               Text(
                   text = msg.body,
                   modifier = Modifier.padding(all = 4.dp),
                   style = MaterialTheme.typography.bodyMedium
               )
           }
       }
   }
}

これでメッセージにマテリアルデザインのスタイル設定を3つ(Color,Typography,Shape)使用して、外観をより良くすることができました!

🎯 リストとアニメーション

これまでは1つのメッセージカードのレイアウトやデザインについてやってきました。
今回はメッセージカードのリスト化、リスト操作時のアニメーションについて改良をしていきます!

☑ リスト化

最初にリスト化していきます。

実際にコードを書く前に!
Jetpack Composeチュートリアルサイトメッセージのリストを作成するの文章下部にあるサンプル データセットからメッセージリストのサンプルをダウンロードして、編集中のプロジェクトのMainActivity.ktと同じ階層にコピーしましょう!

それでは始めます。
LazyColumnitemsを使ってそれぞれのメッセージにこれまで作成してきたデザインを適用していきます。

@Composable
fun Conversation(messages: List<Message>) {
    LazyColumn {
        items(messages) { message ->
            MessageCard(message)
        }
    }
}

@Preview
@Composable
fun PreviewConversation() {
    ComposeTutorialTheme {
        Conversation(SampleData.conversationSample)
    }
}

☑ アニメーション

それでは、アニメーションを作成していきます。
コンテンツサイズと背景色についてアニメーション化して、表示するメッセージをもっと長いテキストに展開する機能を追加します。

// ...
import androidx.compose.foundation.clickable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue

class MainActivity : ComponentActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContent {
           ComposeTutorialTheme {
               Conversation(SampleData.conversationSample)
           }
       }
   }
}

@Composable
fun MessageCard(msg: Message) {
    Row(modifier = Modifier.padding(all = 8.dp)) {
        Image(
            painter = painterResource(R.drawable.profile_picture),
            contentDescription = null,
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
                .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
        )
        Spacer(modifier = Modifier.width(8.dp))

        // We keep track if the message is expanded or not in this
        // variable
        var isExpanded by remember { mutableStateOf(false) }

        // We toggle the isExpanded variable when we click on this Column
        Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {
            Text(
                text = msg.author,
                color = MaterialTheme.colorScheme.secondary,
                style = MaterialTheme.typography.titleSmall
            )

            Spacer(modifier = Modifier.height(4.dp))

            Surface(
                shape = MaterialTheme.shapes.medium,
                shadowElevation = 1.dp,
            ) {
                Text(
                    text = msg.body,
                    modifier = Modifier.padding(all = 4.dp),
                    // If the message is expanded, we display all its content
                    // otherwise we only display the first line
                    maxLines = if (isExpanded) Int.MAX_VALUE else 1,
                    style = MaterialTheme.typography.bodyMedium
                )
            }
        }
    }
}

お疲れ様でした!これで、チュートリアル完了です!

🎉 まとめ

初めてのJetpack Compose、スマホアプリ作成は新しい言語での挑戦ということもあって新鮮でした!
テキストや画像の配置などコーディングするのもわかりやすく、理解が他の言語に比べても早いような気がします!

まだ、チュートリアルをなぞった基礎的なことしかしていませんが、これからいろいろアプリ開発をしていきたいと思っています!

私事なんですが、家計簿アプリを作成したいんですよね。
慢性的にお金がカツカツな状態で自分のお金の流れを記録、管理したくて、どうせなら自分で作ってみようと思った次第です。
出費の記録を早くつけたいので頑張って早く開発したいと思います!

最後までご覧いただきありがとうございます。他にもアプリを作成して記事にしておりますので、良かったら見ていただけると嬉しいです!コメントも待ってます!
それでは!

Discussion