取り組みの背景 — なぜ Antigravity × Jetpack Compose なのか
Android アプリの UI 開発は、Jetpack Compose の登場によって宣言的なコード記述が標準になりましました。しかし、複雑なレイアウトの組み立てやテーマの一貫性維持、アニメーション実装など、UI 開発には依然として多くの手作業が伴います。
ここで Antigravity IDE の AI エージェント機能を組み合わせると、Composable 関数の雛形生成からプレビュー用データの作成、Material Design 3 テーマの自動構成まで、UI 開発のあらゆる工程を効率化できます。ここではAntigravity と Jetpack Compose を組み合わせた実践的なワークフローを、具体的なコード例とともに解説します。
対象読者は、Kotlin と Jetpack Compose の基本を理解しており、AI IDE を活用して開発効率を上げたい方です。
Antigravity で Android プロジェクトをセットアップする
Antigravity で Jetpack Compose プロジェクトを扱うには、まず適切なプロジェクト構成を AI に認識させる点が肝心です。プロジェクトのルートディレクトリを開いた状態で、AGENTS.md ファイルにプロジェクトの技術スタックを記述しておくと、エージェントが生成するコードの精度が大幅に向上します。
// AGENTS.md に記載する技術スタック情報の例
// (Markdownファイルとして記述)
// ## Tech Stack
// - Language: Kotlin 2.1
// - UI Framework: Jetpack Compose (BOM 2026.03.00)
// - Architecture: MVVM + Clean Architecture
// - DI: Hilt
// - Navigation: Compose Navigation
// - Theme: Material Design 3 (Dynamic Color対応)この情報をもとに、Antigravity のエージェントは Compose のベストプラクティスに沿ったコードを生成してくれます。たとえば「ユーザープロフィール画面を作って」と指示するだけで、Material 3 のコンポーネントを使った Composable 関数が MVVM パターンに従って生成されます。
AI でコンポーザブル関数を効率的に生成する
Antigravity のインラインチャット(Cmd+I / Ctrl+I)を使うと、Composable 関数を自然言語から直接生成できます。ポイントは、具体的な UI 要件を伝えることです。
// Antigravity に以下のようなプロンプトを送る:
// 「商品一覧画面のカードコンポーネントを作成して。
// 画像・商品名・価格・お気に入りボタンを含む。
// Material 3のCardコンポーネントを使用。」
// 生成されるコード例:
@Composable
fun ProductCard(
product: Product,
onFavoriteClick: (String) -> Unit,
modifier: Modifier = Modifier
) {
Card(
modifier = modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
shape = RoundedCornerShape(12.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
) {
Column {
// 商品画像
AsyncImage(
model = product.imageUrl,
contentDescription = product.name,
modifier = Modifier
.fillMaxWidth()
.height(200.dp),
contentScale = ContentScale.Crop
)
Column(modifier = Modifier.padding(16.dp)) {
// 商品名
Text(
text = product.name,
style = MaterialTheme.typography.titleMedium,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(4.dp))
// 価格とお気に入りボタン
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "¥${product.price}",
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.primary
)
IconButton(onClick = { onFavoriteClick(product.id) }) {
Icon(
imageVector = if (product.isFavorite)
Icons.Filled.Favorite else Icons.Outlined.FavoriteBorder,
contentDescription = "お気に入り",
tint = if (product.isFavorite)
MaterialTheme.colorScheme.error
else MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}
}
}
}
// 期待される出力: Material 3 のカードUIに商品情報が表示され、
// お気に入りボタンのトグルが動作する生成されたコードは、@Preview アノテーションを追加して Android Studio のプレビュー機能ですぐに確認できます。Antigravity に「プレビュー用の関数も追加して」と指示すれば、サンプルデータ付きのプレビュー関数も自動生成されます。
Material Design 3 テーマを AI で構成する
アプリ全体のテーマ設計は、一貫性のある UI を実現するために欠かせません。Antigravity を使えば、ブランドカラーから Material 3 のカラースキームを自動生成できます。
// プロンプト例:
// 「ブランドカラー #6750A4 をベースに
// Material 3 のダイナミックカラー対応テーマを作成して」
// 生成されるテーマ設定:
private val LightColorScheme = lightColorScheme(
primary = Color(0xFF6750A4),
onPrimary = Color(0xFFFFFFFF),
primaryContainer = Color(0xFFEADDFF),
onPrimaryContainer = Color(0xFF21005D),
secondary = Color(0xFF625B71),
onSecondary = Color(0xFFFFFFFF),
secondaryContainer = Color(0xFFE8DEF8),
onSecondaryContainer = Color(0xFF1D192B),
tertiary = Color(0xFF7D5260),
surface = Color(0xFFFFFBFE),
onSurface = Color(0xFF1C1B1F),
background = Color(0xFFFFFBFE),
error = Color(0xFFB3261E)
)
private val DarkColorScheme = darkColorScheme(
primary = Color(0xFFD0BCFF),
onPrimary = Color(0xFF381E72),
primaryContainer = Color(0xFF4F378B),
onPrimaryContainer = Color(0xFFEADDFF),
secondary = Color(0xFFCCC2DC),
onSecondary = Color(0xFF332D41),
surface = Color(0xFF1C1B1F),
onSurface = Color(0xFFE6E1E5),
background = Color(0xFF1C1B1F),
error = Color(0xFFF2B8B5)
)
@Composable
fun AppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colorScheme = when {
// Android 12以降でダイナミックカラーをサポート
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context)
else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
MaterialTheme(
colorScheme = colorScheme,
typography = AppTypography,
content = content
)
}
// 期待される出力: ライト/ダークテーマが自動切り替えされ、
// Android 12以降ではダイナミックカラーが適用されるテーマのカスタマイズでは、Typography の定義も重要です。「日本語フォントに Noto Sans JP を使った Typography 設定を追加して」と指示すると、ウェイトごとのフォント定義まで含めたコードが生成されます。
LazyColumn / LazyGrid でパフォーマンスを意識したリスト UI を構築する
大量のデータを表示するリスト画面は、パフォーマンスへの配慮が不可欠です。Antigravity のエージェントにパフォーマンス要件を伝えることで、最適化済みのリストコンポーネントを生成できます。
// プロンプト例:
// 「商品一覧を2列グリッドで表示する画面を作成。
// ページング対応、プルリフレッシュ付き。」
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ProductListScreen(
viewModel: ProductListViewModel = hiltViewModel()
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val pullRefreshState = rememberPullToRefreshState()
PullToRefreshBox(
isRefreshing = uiState.isRefreshing,
onRefresh = { viewModel.refresh() },
state = pullRefreshState
) {
LazyVerticalGrid(
columns = GridCells.Fixed(2),
contentPadding = PaddingValues(8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
items(
items = uiState.products,
key = { it.id } // リコンポジション最適化
) { product ->
ProductCard(
product = product,
onFavoriteClick = { viewModel.toggleFavorite(it) }
)
}
// ページング: 末尾にローディングインジケーター
if (uiState.hasMore) {
item(span = { GridItemSpan(2) }) {
LaunchedEffect(Unit) {
viewModel.loadMore()
}
Box(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator()
}
}
}
}
}
}
// 期待される出力: 2列グリッドに商品カードが並び、
// スクロール末尾で自動ページング、上部スワイプでリフレッシュkey パラメータの指定は、リコンポジション時のパフォーマンスに大きく影響します。Antigravity にこの点を明示的に伝えることで、最初からパフォーマンスを意識したコードが生成されます。
さらに詳しいパフォーマンス最適化のテクニックについては、Antigravity AI デバッグ&パフォーマンス最適化 プロフェッショナルガイド で体系的に解説しています。
Compose Navigation と画面遷移アニメーション
複数画面を持つアプリでは、ナビゲーション設計が重要になります。Antigravity を使って、型安全なナビゲーショングラフとカスタム遷移アニメーションを構築しましょう。
// 型安全なルート定義
@Serializable
sealed class Route {
@Serializable
data object ProductList : Route()
@Serializable
data class ProductDetail(val productId: String) : Route()
@Serializable
data object Cart : Route()
}
// ナビゲーションホスト
@Composable
fun AppNavigation(navController: NavHostController = rememberNavController()) {
NavHost(
navController = navController,
startDestination = Route.ProductList,
enterTransition = {
slideIntoContainer(
towards = AnimatedContentTransitionScope.SlideDirection.Left,
animationSpec = tween(300)
)
},
exitTransition = {
slideOutOfContainer(
towards = AnimatedContentTransitionScope.SlideDirection.Left,
animationSpec = tween(300)
)
},
popEnterTransition = {
slideIntoContainer(
towards = AnimatedContentTransitionScope.SlideDirection.Right,
animationSpec = tween(300)
)
},
popExitTransition = {
slideOutOfContainer(
towards = AnimatedContentTransitionScope.SlideDirection.Right,
animationSpec = tween(300)
)
}
) {
composable<Route.ProductList> {
ProductListScreen(
onProductClick = { productId ->
navController.navigate(Route.ProductDetail(productId))
}
)
}
composable<Route.ProductDetail> { backStackEntry ->
val route = backStackEntry.toRoute<Route.ProductDetail>()
ProductDetailScreen(
productId = route.productId,
onBackClick = { navController.popBackStack() },
onCartClick = { navController.navigate(Route.Cart) }
)
}
composable<Route.Cart> {
CartScreen(onBackClick = { navController.popBackStack() })
}
}
}
// 期待される出力: 画面間をスライドアニメーション付きで遷移し、
// 戻る操作では逆方向のアニメーションが再生されるAntigravity のエージェントに「画面遷移のアニメーションもカスタマイズして」と追加指示を送ると、フェードやスケールなど多様なトランジションパターンを提案してくれます。
まとめ
Antigravity IDE と Jetpack Compose を組み合わせることで、Android UI 開発の生産性を大幅に向上させることができます。本記事で紹介したポイントをまとめると、AGENTS.md によるプロジェクト情報の共有、インラインチャットを使った Composable 関数の生成、Material 3 テーマの自動構成、パフォーマンスを意識したリスト実装、そして型安全なナビゲーション設計です。
AI が生成したコードをそのまま使うのではなく、プレビュー機能やテストで検証しながら改善を重ねることで、品質と開発速度を両立できます。Antigravity のエージェント機能をさらに活用したい方には、AGENTS.md によるマルチエージェント設計 も合わせてご覧ください。