Jetpack Compose入門(3) Hello World! テンプレート利用編

今回と次回は、Jetpack ComposeでHello Worldに挑戦します。まず今回は、Android StudioのJetpack Compose用プロジェクトテンプレートを使って、とにかくJetpack Composeを動かしてみます。しかし、テンプレートを使うと、必要な設定などが自動で行われる一方、不要なものまで勝手に追加されていたりして、純粋にJetpack Composeを動かすために何が必要なのかが見えづらい部分がありますので、次回は、必要な設定を自分で追加して動かしてみます。

プロジェクト作成

まずはテンプレートを選択してプロジェクトを作成します。

File > New > New Projectをクリックします。

Empty Compose Activityを選択し、Nextをクリックします。

プロジェクト名などを入力し、Finishをクリックします。

ビルドして実行

このプロジェクトテンプレートは、作成したそのままでビルドが通るように準備されています。ソースコードは一切手を加えず、さっそくビルドして実行してみましょう。”Hello Android!”と表示されるのを確認できます。文字小さいですね(笑) このテンプレートではテーマが有効になっているので、ダークモードのON/OFFで色が変わります。

ダークモードOFF
ダークモードON

ソースコード確認

ここからは MainActivity.ktのソースコードを見ながら、実際に何をやっているのかを確認していきます。

MainActivity

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            HelloCompose1Theme {
                // A surface container using the 'background' color from the theme
                Surface(color = MaterialTheme.colors.background) {
                    Greeting("Android")
                }
            }
        }
    }
}

MainActivityは、AppCompatActivityではなくComponentActivityのサブクラスになっています。AppCompatActivityComponentActivityのサブクラスです。継承関係は図のようになっています。ComponentActivityにFragmentの管理機能などを加えたものがFragmentActivityで、それに更にActionBarなどの機能を加えたものがAppCompatActivityです。Jetpack Composeでは基本的にFragmentは使わないので、基底クラスのComponentActivityが使われているのだと思われます。

onCreate()では、setContentView()ではなくsetContent()を呼び出しています。setContent()androidx.activity.composeパッケージに定義されている(つまりJetpack Compose対応として追加された)、ComponentActivityの拡張関数です。引数に与えたComposableにより作成されるUIを、ActivityのルートViewとして設定します。ここで出てきた”Composable”とは、Jetpack Composeの仕組みによりUIを作成する関数のことです。Jetpack ComposeではComposableな関数を入れ子で呼び出すことにより、UIの階層を宣言します。setContent()の引数に与えるComposableが、UI階層のルートになります。

ちなみに、setContentには”( )”がなくて”{ }”がついていますが、これはKotlinの記法によるもので、関数の最後のラムダ引数が( )の外側に出され、それにより( )内の引数がなくなったので( )自体が省略された状態です。つまりsetContent{ ... }はComposable関数のラムダ式をsetContentの引数として与えていることを意味しています。Jetpack Composeではこの書き方が多用されますので、慣れていきましょう。

HelloCompose1Theme()はプロジェクトテンプレートにより自動作成されるComposableで、Theme.ktに定義されています。詳しくはテーマについて説明する回で見ていきますが、このComposableで、ライトテーマとダークテーマの設定をしており、これより下の階層でMaterialTheme.colorsから呼び出す色を指定しています。

Surface()はJetpack Composeでマテリアルデザインを実現するための基本ウィジェットです。当然これもComposableです。ここではcolor引数にMaterialTheme.colors.backgroundを指定しているので、HelloCompose1Theme()の中で指定したアプリのテーマの背景色が適用されます。Jetpack Composeで背景色を指定するには、個別のウィジェットにbackgroundを設定するのではなく、Surfaceのcolorを設定するのがよいとされています。

注: 要素の背景色を設定する際は、Surface を使用することをおすすめします。Surface は適切なコンテンツ色を設定します。Modifier.background() で直接呼び出すと適切なコンテンツ色が設定されないため、ご注意ください。

https://developer.android.com/jetpack/compose/themes?hl=ja#content-color

やっとGreeting()までたどり着きました。Greeting()が、”Hello Android!”という文字列を表示しているComposableです。次はGreeting()の実装を見ていきます。

Composableの実装

このサンプルのUI本体の実装は、Greeting()のみです。Greeting()MainActivity.ktのファイル内に定義されていますが、MainActivityクラスの外、トップレベル関数として定義されています。

Greeting()は、引数として受け取った文字列に”Hello”をつけて画面に表示するようになっています。Text()は、text引数に指定した文字列を表示するComposableです。従来のViewシステムではTextViewに相当するUIウィジェットになりますが、Jetpack ComposeはViewとは別物なので、Text ComposableはTextViewとは全くの別物になります。Jetpack Composeでは、Composableを呼び出す関数もComposableである必要があります。したがって、Text()を呼び出しているGreeting()もComposableである必要があるので、@Composableアノテーションがついています。

@Composable
fun Greeting(name: String) {
    Text(text = "Hello $name!")
}

HelloCompose1アプリとしてのMainActivityの実装は以上です。しかし、MainActivity.ktにはあと一つ、関数が実装されています。

Preview

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

@PreviewアノテーションがついたComposable関数は、Android Studioの画面上でプレビューを表示するための関数です。MainActivityタブの右上のSplitをクリックすると、DefaultPreview()のプレビューが表示されます。showBackground = trueを指定することで、プレビューの背景が白になっています。この白色は、HelloCompose1Theme()で定義しているアプリのテーマとは無関係です。Greeting()の中ではMaterialThemeを利用していないので、HelloCompose1Theme()は特に何も仕事をしていません。このプロジェクトテンプレートの中でも紛らわしい部分だと思います。

まとめ

以上で、Empty Compose Activityテンプレートを使ったHello Worldは完了です。テンプレートをそのまま実行し、テキストが表示されることを確認しました。また、テーマが適用されていることも確認しました。ソースコードは、MainActivity.ktを中心に確認しました。

まだ確認できていないこととしては、Gradleの設定などがあります。この辺りは次回、手動で一つ一つ設定を行いながら見ていきたいと思います。