Contents
1. プロジェクト作成と依存関係の自動設定
手順
| 手順 | 操作内容 |
|---|---|
| 1 | File → New → Compose Activity を選択 |
| 2 | 「Empty Compose Activity」を選び、プロジェクト名・保存先を入力 |
| 3 | IDE が build.gradle.kts と libs.versions.toml を自動生成 |
生成されたビルドスクリプト(抜粋)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) } android { compileSdk = 34 defaultConfig { applicationId = "com.example.mycomposeapp" minSdk = 21 targetSdk = 34 versionCode = 1 versionName = "1.0" } buildFeatures { compose = true } composeOptions { kotlinCompilerExtensionVersion = "1.6.0" } } dependencies { // BOM による Compose ライブラリの一括管理 implementation(platform(libs.compose.bom)) implementation(libs.compose.ui) implementation(libs.compose.material3) implementation(libs.activity.compose) } |
libs.versions.toml(自動生成例)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[versions] # Android Studio が推奨する最新の Compose BOM バージョンです。 # リリース状況は公式サイトで随時確認してください。 compose-bom = "2024.03" kotlin = "1.9.22" [libraries] compose-bom = { module = "androidx.compose:compose-bom", version.ref = "compose-bom" } compose-ui = { module = "androidx.compose.ui:ui" } compose-material3 = { module = "androidx.compose.material3:material3" } activity-compose = { module = "androidx.activity:activity-compose" } [plugins] android-application = { id = "com.android.application", version = "8.5.0" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } |
※ バージョンは執筆時点の最新安定版です。実際にプロジェクトを作成する前に、Maven Central の Compose BOM ページで最新版をご確認ください。
余談:Gradle バージョン管理のベストプラクティス
libs.versions.tomlを使うと、プロジェクト全体で同一バージョンが保証されます。platform(libs.compose.bom)が BOM(Bill of Materials)として機能し、個別にバージョンを指定する手間が省けるので、依存関係の衝突リスクが大幅に低減します。
2. @Composable とプレビューで UI を即確認
サンプルコード
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
@Composable fun Greeting(name: String, onClick: () -> Unit) { Column( modifier = Modifier .fillMaxSize() .padding(16.dp), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = "Hello, $name!", style = MaterialTheme.typography.headlineMedium ) Spacer(modifier = Modifier.height(12.dp)) Button(onClick = onClick) { Text("クリック") } } } @Preview(showBackground = true) @Composable fun GreetingPreview() { var label by remember { mutableStateOf("Compose") } Greeting(name = label) { label = "Clicked!" } } |
Greetingが UI 本体。GreetingPreviewではrememberとmutableStateOfを使って、プレビュー上でも状態遷移を確認できます。
プレビュー活用のコツ
| テクニック | 効果 |
|---|---|
showBackground = true |
背景色が自動で付くので、テキストやボタンの可読性が向上 |
uiMode = UI_MODE_NIGHT_YES |
ダークテーマでも見た目を確認できる |
device = "spec:width=411dp,height=891dp" |
任意デバイスサイズでプレビュー可能 |
3. 基本レイアウトと Material 3 ウィジェット
3‑1. レイアウトコンポーネントの使い分け
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@Composable fun LayoutSample() { Column( modifier = Modifier .fillMaxSize() .padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) { Text("左") Text("右") } Box( modifier = Modifier .size(100.dp) .background(Color.Cyan), contentAlignment = Alignment.Center ) { Text("重ね合わせ") } } } |
- Column – 縦方向に子要素を並べる。
verticalArrangementで余白や位置調整が可能。 - Row – 横方向に子要素を配置。
horizontalArrangementが同様の役割を果たす。 - Box – 重ね合わせレイアウト。
contentAlignmentで子要素の基準点を指定でき、背景や装飾にも便利。
3‑2. Material 3 ウィジェットの実装例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
@Composable fun FormSample() { var name by remember { mutableStateOf("") } Column( modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp) ) { TextField( value = name, onValueChange = { name = it }, label = { Text("名前を入力") }, singleLine = true ) Button(onClick = { /* 送信ロジック */ }) { Text("送信") } } } |
MaterialThemeが提供するカラー・タイポグラフィは自動で適用され、アクセシビリティ(コントラスト比)も確保されています。TextFieldのlabelパラメータは、入力中でも常に可視状態を保ち、ユーザー体験を向上させます。
4. 状態管理とイベント処理の実践
4‑1. ローカルステート (remember) と再コンポーズ
|
1 2 3 4 5 6 7 8 9 |
@Composable fun Counter() { var count by remember { mutableStateOf(0) } Button(onClick = { count++ }) { Text("クリック回数: $count") } } |
mutableStateOfが保持する値が変化すると、この関数だけが再コンポーズされます。- 再描画対象を最小限に抑えることで、パフォーマンスの低下を防げます。
4‑2. State Hoisting(状態持ち上げ)とコールバック
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// 子コンポーネント:UI のみ担当 @Composable fun ToggleButton(isOn: Boolean, onToggle: () -> Unit) { Button(onClick = onToggle) { Text(if (isOn) "ON" else "OFF") } } // 親コンポーネント:状態管理 @Composable fun ToggleScreen() { var switchedOn by remember { mutableStateOf(false) } ToggleButton(isOn = switchedOn) { switchedOn = !switchedOn } } |
- 利点
- 子コンポーネントはテストしやすく、再利用性が向上。
- 状態の流れが一方向になるので、デバッグが容易になる。
4‑3. ViewModel と Compose の連携(簡易例)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class CounterViewModel : ViewModel() { private val _count = mutableStateOf(0) val count: State<Int> get() = _count fun increment() { _count.value++ } } @Composable fun CounterWithVm(viewModel: CounterViewModel = viewModel()) { val count by viewModel.count Button(onClick = { viewModel.increment() }) { Text("クリック回数: $count") } } |
mutableStateOfを ViewModel に持たせると、画面回転やプロセス再生成でも状態が保持されます。byデリゲートで UI 側のコードがシンプルに。
5. テーマ設定・デバッグ活用・XML から Compose への移行ポイント
5‑1. カラーパレットとダークテーマのカスタマイズ
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
private val LightColors = lightColorScheme( primary = Color(0xFF6200EE), secondary = Color(0xFF03DAC6) ) private val DarkColors = darkColorScheme( primary = Color(0xFFBB86FC), secondary = Color(0xFF03DAC6) ) @Composable fun MyAppTheme(content: @Composable () -> Unit) { val colors = if (isSystemInDarkTheme()) DarkColors else LightColors MaterialTheme(colorScheme = colors, typography = Typography(), content = content) } |
MyAppThemeをアプリのエントリポイント(例:MainActivity.setContent {})でラップすれば、全画面に統一テーマが適用されます。- テーマは
MaterialTheme.colorSchemeとMaterialTheme.typographyから取得できるので、個別ウィジェットでカラーやフォントをハードコーディングする必要がなくなります。
5‑2. Compose Inspector & Layout Inspector の使い方
| ツール | 開き方 | 主な活用シーン |
|---|---|---|
| Compose Inspector | プレビュー画面右上の Inspector タブ | コンポーズ要素のプロパティや Modifier が一目で分かる |
| Layout Inspector | View > Tool Windows > Layout Inspector(実機/エミュレータ実行中) |
実際に動いている UI ツリーをツリービューで確認し、レイアウト崩れやステートの変化を追跡 |
デバッグ時のヒント
- 「Recompose Count」 を有効にすると、各コンポーズ関数が何回再描画されたかが表示され、過剰な再コンポーズをすぐに検出できます。
Modifier.debugBorder()(デバッグ専用)で要素の境界線を可視化し、レイアウトミスを特定しやすくします。
5‑3. XML → Compose 移行チェックリスト
| 項目 | XML の書き方 | Compose への置換例 |
|---|---|---|
| レイアウト構造 | <LinearLayout android:orientation="vertical"> |
Column { … } |
| 属性 → Modifier | android:padding="16dp" |
.padding(16.dp) |
| 背景色 | android:background="@color/primary" |
.background(Color(0xFF6200EE)) |
| 文字列リソース | @string/app_name |
stringResource(R.string.app_name) |
| 可視性 | android:visibility="gone" |
if (visible) { … } |
- ポイント:Compose ではすべてが Kotlin のコードになるため、属性は
Modifier系の拡張関数で統一的に扱います。 - 移行時は「レイアウト階層 → コンポーズツリー」と捉えると、構造変換がスムーズです。
6. まとめ
- Android Studio Giraffe+ だけで最新 Compose と Kotlin が自動設定されるので、環境構築はほぼワンクリック。
@Composableとプレビューを組み合わせれば、コードを書いた瞬間に UI を確認でき、開発サイクルが大幅に短縮。Column / Row / Boxと Material 3 ウィジェットでシンプルかつアクセシブルな画面を作成しやすい。- 状態は
rememberか ViewModel に保持し、必要に応じて State Hoisting を実践することで保守性が向上。 MaterialThemeによるテーマ一括管理と Android Studio の Compose Inspector / Layout Inspector がデバッグを強力サポート。- XML からの移行は「レイアウト → コンポーズ」「属性 → Modifier」の二軸で考えれば、スムーズに進められる。
次のステップ:本稿で作成したプロジェクトに Navigation Compose や Hilt(DI)を組み込み、実務レベルのアーキテクチャへ拡張してみましょう。公式サンプルや codelab が多数用意されているので、ぜひ手を動かしながら学習してください。