jpskill.com
🛠️ 開発・MCP コミュニティ

jetpack-compose

Jetpack Composeを活用し、宣言的なUI構築、状態管理、テーマ設定、アニメーション、パフォーマンス最適化といった、Androidアプリ開発におけるUI実装を効率的に進めるSkill。

📜 元の英語説明(参考)

Jetpack Compose patterns for declarative UI, state management, theming, animations, and performance optimization.

🇯🇵 日本人クリエイター向け解説

一言でいうと

Jetpack Composeを活用し、宣言的なUI構築、状態管理、テーマ設定、アニメーション、パフォーマンス最適化といった、Androidアプリ開発におけるUI実装を効率的に進めるSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o jetpack-compose.zip https://jpskill.com/download/10670.zip && unzip -o jetpack-compose.zip && rm jetpack-compose.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/10670.zip -OutFile "$d\jetpack-compose.zip"; Expand-Archive "$d\jetpack-compose.zip" -DestinationPath $d -Force; ri "$d\jetpack-compose.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して jetpack-compose.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → jetpack-compose フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

Jetpack Compose のパターン

Android 向けのモダンな宣言型 UI パターンです。

状態管理

State Hoisting

// ✅ 正しい: ステートレスな composable
@Composable
fun Counter(
    count: Int,
    onIncrement: () -> Unit,
    modifier: Modifier = Modifier
) {
    Row(modifier = modifier) {
        Text("Count: $count")
        Button(onClick = onIncrement) {
            Text("+")
        }
    }
}

// 親が状態を所有
@Composable
fun CounterScreen() {
    var count by rememberSaveable { mutableStateOf(0) }

    Counter(
        count = count,
        onIncrement = { count++ }
    )
}

Remember のバリエーション

// remember - 再コンポーズを生き残る
val alpha by remember { mutableStateOf(1f) }

// rememberSaveable - 設定変更を生き残る
var count by rememberSaveable { mutableStateOf(0) }

// キー付きの remember - キーの変更でリセットされる
val animation = remember(itemId) { Animatable(0f) }

// derivedStateOf - 計算され、結果が変更されたときのみ更新される
val isValid by remember {
    derivedStateOf { email.isNotBlank() && password.length >= 8 }
}

コンポジションのパターン

Slot API

@Composable
fun AppBar(
    title: @Composable () -> Unit,
    navigationIcon: @Composable () -> Unit = {},
    actions: @Composable RowScope.() -> Unit = {}
) {
    TopAppBar(
        title = { title() },
        navigationIcon = { navigationIcon() },
        actions = actions
    )
}

// 使用例
AppBar(
    title = { Text("Home") },
    navigationIcon = { IconButton(onClick = {}) { Icon(Icons.Default.Menu, null) } },
    actions = {
        IconButton(onClick = {}) { Icon(Icons.Default.Search, null) }
    }
)

Modifier パターン

@Composable
fun CustomButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,  // 最初のオプションパラメータ
    enabled: Boolean = true,
    content: @Composable RowScope.() -> Unit
) {
    Button(
        onClick = onClick,
        modifier = modifier,  // 最初に modifier を適用
        enabled = enabled,
        content = content
    )
}

副作用

LaunchedEffect

@Composable
fun HomeScreen(viewModel: HomeViewModel) {
    // 一度だけ実行される
    LaunchedEffect(Unit) {
        viewModel.loadData()
    }

    // キーが変更されたときに実行される
    LaunchedEffect(userId) {
        viewModel.loadUser(userId)
    }
}

DisposableEffect

@Composable
fun LifecycleObserver(onResume: () -> Unit) {
    val lifecycleOwner = LocalLifecycleOwner.current

    DisposableEffect(lifecycleOwner) {
        val observer = LifecycleEventObserver { _, event ->
            if (event == Lifecycle.Event.ON_RESUME) onResume()
        }
        lifecycleOwner.lifecycle.addObserver(observer)

        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }
}

テーマ

Material 3

@Composable
fun AppTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {
    val colorScheme = if (darkTheme) DarkColorScheme else LightColorScheme

    MaterialTheme(
        colorScheme = colorScheme,
        typography = AppTypography,
        content = content
    )
}

// 使用例
val backgroundColor = MaterialTheme.colorScheme.surface
val textStyle = MaterialTheme.typography.bodyLarge

リスト

LazyColumn

LazyColumn {
    items(
        items = users,
        key = { it.id }  // パフォーマンス上重要
    ) { user ->
        UserItem(user = user)
    }
}

アニメーション

値のアニメーション

val alpha by animateFloatAsState(
    targetValue = if (visible) 1f else 0f,
    animationSpec = tween(durationMillis = 300)
)

val size by animateDpAsState(
    targetValue = if (expanded) 200.dp else 100.dp
)

AnimatedContent

AnimatedContent(
    targetState = state,
    transitionSpec = {
        fadeIn() togetherWith fadeOut()
    }
) { targetState ->
    when (targetState) {
        is Loading -> LoadingContent()
        is Success -> SuccessContent(targetState.data)
        is Error -> ErrorContent()
    }
}

覚えておいてください: Compose は宣言型です。UI を記述し、命令しないでください。

📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Jetpack Compose Patterns

Modern declarative UI patterns for Android.

State Management

State Hoisting

// ✅ CORRECT: Stateless composable
@Composable
fun Counter(
    count: Int,
    onIncrement: () -> Unit,
    modifier: Modifier = Modifier
) {
    Row(modifier = modifier) {
        Text("Count: $count")
        Button(onClick = onIncrement) {
            Text("+")
        }
    }
}

// Parent owns state
@Composable
fun CounterScreen() {
    var count by rememberSaveable { mutableStateOf(0) }

    Counter(
        count = count,
        onIncrement = { count++ }
    )
}

Remember Variants

// remember - Survives recomposition
val alpha by remember { mutableStateOf(1f) }

// rememberSaveable - Survives config change
var count by rememberSaveable { mutableStateOf(0) }

// remember with key - Resets on key change
val animation = remember(itemId) { Animatable(0f) }

// derivedStateOf - Computed, updates only when result changes
val isValid by remember {
    derivedStateOf { email.isNotBlank() && password.length >= 8 }
}

Composition Patterns

Slot API

@Composable
fun AppBar(
    title: @Composable () -> Unit,
    navigationIcon: @Composable () -> Unit = {},
    actions: @Composable RowScope.() -> Unit = {}
) {
    TopAppBar(
        title = { title() },
        navigationIcon = { navigationIcon() },
        actions = actions
    )
}

// Usage
AppBar(
    title = { Text("Home") },
    navigationIcon = { IconButton(onClick = {}) { Icon(Icons.Default.Menu, null) } },
    actions = {
        IconButton(onClick = {}) { Icon(Icons.Default.Search, null) }
    }
)

Modifier Pattern

@Composable
fun CustomButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,  // First optional parameter
    enabled: Boolean = true,
    content: @Composable RowScope.() -> Unit
) {
    Button(
        onClick = onClick,
        modifier = modifier,  // Apply modifier first
        enabled = enabled,
        content = content
    )
}

Side Effects

LaunchedEffect

@Composable
fun HomeScreen(viewModel: HomeViewModel) {
    // Runs once
    LaunchedEffect(Unit) {
        viewModel.loadData()
    }

    // Runs when key changes
    LaunchedEffect(userId) {
        viewModel.loadUser(userId)
    }
}

DisposableEffect

@Composable
fun LifecycleObserver(onResume: () -> Unit) {
    val lifecycleOwner = LocalLifecycleOwner.current

    DisposableEffect(lifecycleOwner) {
        val observer = LifecycleEventObserver { _, event ->
            if (event == Lifecycle.Event.ON_RESUME) onResume()
        }
        lifecycleOwner.lifecycle.addObserver(observer)

        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }
}

Theming

Material 3

@Composable
fun AppTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {
    val colorScheme = if (darkTheme) DarkColorScheme else LightColorScheme

    MaterialTheme(
        colorScheme = colorScheme,
        typography = AppTypography,
        content = content
    )
}

// Usage
val backgroundColor = MaterialTheme.colorScheme.surface
val textStyle = MaterialTheme.typography.bodyLarge

Lists

LazyColumn

LazyColumn {
    items(
        items = users,
        key = { it.id }  // Critical for performance
    ) { user ->
        UserItem(user = user)
    }
}

Animations

Animate Values

val alpha by animateFloatAsState(
    targetValue = if (visible) 1f else 0f,
    animationSpec = tween(durationMillis = 300)
)

val size by animateDpAsState(
    targetValue = if (expanded) 200.dp else 100.dp
)

AnimatedContent

AnimatedContent(
    targetState = state,
    transitionSpec = {
        fadeIn() togetherWith fadeOut()
    }
) { targetState ->
    when (targetState) {
        is Loading -> LoadingContent()
        is Success -> SuccessContent(targetState.data)
        is Error -> ErrorContent()
    }
}

Remember: Compose is declarative. Describe the UI, don't command it.