Skip to main content

android-design

Material Design 3 and Android platform guidelines. Use when building Android apps with Jetpack Compose or XML layouts, implementing Material You, navigation, or accessibility. Triggers on tasks involving Android UI, Compose components, dynamic color, or Material Design compliance.

ソース情報

リポジトリ
dirnbauer/webconsulting-skills
ソースの最終更新活動
2026年5月27日 16:08
検出された SKILL.md の言語
英語
スター
33
フォーク
6

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

ファイルエクスプローラー
4 ファイル

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
android-design
description
Material Design 3 and Android platform guidelines. Use when building Android apps with Jetpack Compose or XML layouts, implementing Material You, navigation, or accessibility. Triggers on tasks involving Android UI, Compose components, dynamic color, or Material Design compliance.
# Android Platform Design Guidelines — Material Design 3 ## 1. Material You & Theming [CRITICAL] ### 1.1 Dynamic Color Enable dynamic color derived from the user's wallpaper. Dynamic color is the default on Android 12+ and should be the primary theming strategy. ```kotlin // Compose: Dynamic color theme @Composable fun AppTheme( darkTheme: Boolean = isSystemInDarkTheme(), dynamicColor: Boolean = true, content: @Composable () -> Unit ) { val colorScheme = when { 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 ) } ``` ```xml <!-- XML: Dynamic color in themes.xml --> <style name="Theme.App" parent="Theme.Material3.DayNight.NoActionBar"> <item name="dynamicColorThemeOverlay">@style/ThemeOverlay.Material3.DynamicColors.DayNight</item> </style> ``` **Rules:** - R1.1: Always provide a fallback static color scheme for devices below Android 12. - R1.2: Never hardcode color hex values in components. Always reference color roles from the theme. - R1.3: Test with at least 3 different wallpapers to verify dynamic color harmony. ### 1.2 Color Roles Material 3 defines a structured set of color roles. Use them semantically, not aesthetically. | Role | Usage | On-Role | |------|-------|---------| | `primary` | Key actions, active states, FAB | `onPrimary` | | `primaryContainer` | Less prominent primary elements | `onPrimaryContainer` | | `secondary` | Supporting UI, filter chips | `onSecondary` | | `secondaryContainer` | Navigation bar active indicator | `onSecondaryContainer` | | `tertiary` | Accent, contrast, complementary | `onTertiary` | | `tertiaryContainer` | Input fields, less prominent accents | `onTertiaryContainer` | | `surface` | Backgrounds, cards, sheets | `onSurface` | | `surfaceVariant` | Decorative elements, dividers | `onSurfaceVariant` | | `error` | Error states, destructive actions | `onError` | | `errorContainer` | Error backgrounds | `onErrorContainer` | | `outline` | Borders, dividers | — | | `outlineVariant` | Subtle borders | — | | `inverseSurface` | Snackbar background | `inverseOnSurface` | ```kotlin // Correct: semantic color roles Text( text = "Error message", color = MaterialTheme.colorScheme.error ) Surface(color = MaterialTheme.colorScheme.errorContainer) { Text(text = "Error detail", color = MaterialTheme.colorScheme.onErrorContainer) } // WRONG: hardcoded colors Text(text = "Error", color = Color(0xFFB00020)) // Anti-pattern ``` **Rules:** - R1.4: Every foreground element must use the matching `on` color role for its background (e.g., `onPrimary` text on `primary` background). - R1.5: Use `surface` and its variants for backgrounds. Never use `primary` or `secondary` as large background areas. - R1.6: Use `tertiary` sparingly for accent and complementary contrast only. ### 1.3 Light and Dark Themes Support both light and dark themes. Respect the system setting by default. ```kotlin // Compose: Detect system theme val darkTheme = isSystemInDarkTheme() ``` **Rules:** - R1.7: Always support both light and dark themes. Never ship light-only. - R1.8: Dark theme surfaces use elevation-based tonal mapping, not pure black (#000000). Use `surface` color roles which handle this automatically. - R1.9: Provide a manual theme override in app settings (System / Light / Dark). ### 1.4 Custom Color Seeds When branding requires custom colors, provide a seed color and generate tonal palettes using Material Theme Builder. ```kotlin // Custom color scheme with brand seed private val BrandLightColorScheme = lightColorScheme( primary = Color(0xFF1B6D2F), onPrimary = Color(0xFFFFFFFF), primaryContainer = Color(0xFFA4F6A8), onPrimaryContainer = Color(0xFF002107), // ... generate full palette from seed ) ``` **Rules:** - R1.10: Generate tonal palettes from seed colors using Material Theme Builder. Never manually pick individual tones. - R1.11: When using custom colors, still support dynamic color as the default and use custom colors as fallback. --- ## 2. Navigation [CRITICAL] ### 2.1 Navigation Bar (Bottom) The primary navigation pattern for phones with 3-5 top-level destinations. ```kotlin // Compose: Navigation Bar NavigationBar { items.forEachIndexed { index, item -> NavigationBarItem( icon = { Icon( imageVector = if (selectedItem == index) item.filledIcon else item.outlinedIcon, contentDescription = item.label ) }, label = { Text(item.label) }, selected = selectedItem == index, onClick = { selectedItem = index } ) } } ``` **Rules:** - R2.1: Use Navigation Bar for 3-5 top-level destinations on compact screens. Never use for fewer than 3 or more than 5. - R2.2: Always show labels on navigation bar items. Icon-only navigation bars are not permitted. - R2.3: Use filled icons for the selected state and outlined icons for unselected states. - R2.4: The active indicator uses `secondaryContainer` color. Do not override this. ### 2.2 Navigation Rail For medium and expanded screens (tablets, foldables, desktop). ```kotlin // Compose: Navigation Rail for larger screens NavigationRail( header = { FloatingActionButton( onClick = { /* primary action */ }, containerColor = MaterialTheme.colorScheme.tertiaryContainer ) { Icon(Icons.Default.Add, contentDescription = "Create") } } ) { items.forEachIndexed { index, item -> NavigationRailItem( icon = { Icon(item.icon, contentDescription = item.label) }, label = { Text(item.label) }, selected = selectedItem == index, onClick = { selectedItem = index } ) } } ``` **Rules:** - R2.5: Use Navigation Rail on medium (600-839dp) and expanded (840dp+) window sizes. Pair it with Navigation Bar on compact. - R2.6: Optionally include a FAB in the rail header for the primary action. - R2.7: Labels are optional on the rail but recommended for clarity. ### 2.3 Navigation Drawer For 5+ destinations or complex navigation hierarchies, typically on expanded screens. ```kotlin // Compose: Permanent Navigation Drawer for large screens PermanentNavigationDrawer( drawerContent = { PermanentDrawerSheet { Text("App Name", modifier = Modifier.padding(16.dp), style = MaterialTheme.typography.titleMedium) HorizontalDivider() items.forEach { item -> NavigationDrawerItem( label = { Text(item.label) }, selected = item == selectedItem, onClick = { selectedItem = item }, icon = { Icon(item.icon, contentDescription = null) } ) } } } ) { Scaffold { /* page content */ } } ``` **Rules:** - R2.8: Use modal drawer on compact screens, permanent drawer on expanded screens. - R2.9: Group drawer items into sections with dividers and section headers. ### 2.4 Predictive Back Gesture Android 13+ supports predictive back with an animation preview. ```kotlin // Compose: Predictive back with BackHandler (androidx.activity.compose) BackHandler(enabled = true) { // Called when back is confirmed; navigate back in your nav controller navController.popBackStack() } ``` ```kotlin // Compose: Predictive back progress animation using predictiveBackHandler modifier // (androidx.activity:activity-compose 1.8+) Modifier.predictiveBackHandler(enabled = true) { progress -> // progress is a Flow<BackEventCompat> with x, y, swipeEdge, progress (0.0–1.0) progress.collect { backEvent -> animationState = backEvent.progress } } ``` ```xml <!-- AndroidManifest.xml: opt in to predictive back --> <application android:enableOnBackInvokedCallback="true"> ``` **Rules:** - R2.10: Opt in to predictive back in the manifest. In **Compose** apps, use `BackHandler` (from `androidx.activity.compose`) to intercept back events. In **View-based** apps, implement `OnBackInvokedCallback` (API 33+) or `OnBackPressedCallback` (AndroidX) instead of overriding `onBackPressed()`. - R2.11: The system back gesture navigates back in the navigation stack. The Up button (toolbar arrow) navigates up in the app hierarchy. These may differ. - R2.12: Never intercept system back to show "are you sure?" dialogs unless there is unsaved user input. - R2.13: Do not suppress the system-provided back preview animation. If you implement custom enter/exit transitions, interpolate them using `BackEventCompat.progress` (0.0–1.0) and respect `BackEventCompat.swipeEdge` (`EDGE_LEFT`/`EDGE_RIGHT`) so the exiting screen scales down and shifts toward the initiating edge, matching the system animation. - R2.14: Prefer recognition over recall. Keep destinations labeled, selected state visible, and back-stack context preserved so users do not reconstruct where they are after every navigation step. ```kotlin // Compose: drive a custom animation from predictive back progress Modifier.predictiveBackHandler(enabled = true) { progress -> progress.collect { backEvent -> // backEvent.progress: 0.0 (gesture start) → 1.0 (committed) // backEvent.swipeEdge: BackEventCompat.EDGE_LEFT or EDGE_RIGHT exitScale = 1f - (backEvent.progress * 0.1f) exitOffsetX = if (backEvent.swipeEdge == BackEventCompat.EDGE_LEFT) -backEvent.progress * 32.dp.toPx() else backEvent.progress * 32.dp.toPx() } } ``` ### 2.5 Navigation Component Selection | Screen Size | 3-5 Destinations | 5+ Destinations | |-------------|-------------------|-----------------| | Compact (< 600dp) | Navigation Bar | Modal Drawer + Navigation Bar | | Medium (600-839dp) | Navigation Rail | Modal Drawer + Navigation Rail | | Expanded (840dp+) | Navigation Rail | Permanent Drawer | --- ## 3. Layout & Responsive [HIGH] ### 3.1 Window Size Classes Use window size classes for adaptive layouts, not raw pixel breakpoints. ```kotlin // Compose: Window size classes val windowSizeClass = calculateWindowSizeClass(this) when (windowSizeClass.widthSizeClass) { WindowWidthSizeClass.Compact -> CompactLayout() WindowWidthSizeClass.Medium -> MediumLayout() WindowWidthSizeClass.Expanded -> ExpandedLayout() } ``` | Class | Width | Typical Device | Columns | |-------|-------|----------------|---------| | Compact | < 600dp | Phone portrait | 4 | | Medium | 600-839dp | Tablet portrait, foldable | 8 | | Expanded | 840dp+ | Tablet landscape, desktop | 12 | **Rules:** - R3.1: Always use `WindowSizeClass` from `material3-window-size-class` for responsive layout decisions. - R3.2: Never use fixed pixel breakpoints. Device categories are fluid. - R3.3: Support all three width size classes. At minimum, compact and expanded. ### 3.2 Material Grid Apply canonical Material grid margins and gutters. | Size Class | Margins | Gutters | Columns | |------------|---------|---------|---------| | Compact | 16dp | 8dp | 4 | | Medium | 24dp | 16dp | 8 | | Expanded | 24dp | 24dp | 12 | **Rules:** - R3.4: Content should not span the full width on expanded screens. Use a max content width of ~840dp or list-detail layout. - R3.5: Apply consistent horizontal margins matching the grid spec. ### 3.3 Edge-to-Edge Display Android 15+ enforces edge-to-edge. All apps should draw behind system bars. ```kotlin // Compose: Edge-to-edge setup class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() super.onCreate(savedInstanceState) setContent { Scaffold( modifier = Modifier.fillMaxSize(), // Scaffold handles insets for top/bottom bars automatically ) { innerPadding -> Content(modifier = Modifier.padding(innerPadding)) } } } } ``` **Rules:** - R3.6: Call `enableEdgeToEdge()` before `setContent`. Draw behind both status bar and navigation bar. - R3.7: Use `WindowInsets` to pad content away from system bars. `Scaffold` handles this for top bar and bottom bar content automatically. - R3.8: Scrollable content should scroll behind transparent system bars with appropriate inset padding at the top and bottom of the list. ### 3.4 Foldable Device Support ```kotlin // Compose: Detect fold posture val foldingFeatures = WindowInfoTracker.getOrCreate(context) .windowLayoutInfo(context) .collectAsState(initial = WindowLayoutInfo(emptyList())) ``` **Rules:** - R3.9: Detect hinge/fold position and avoid placing critical content across the fold. - R3.10: Use `ListDetailPaneScaffold` or `SupportingPaneScaffold` from Material3 adaptive library for foldable-aware layouts. --- ## 4. Typography [HIGH] ### 4.1 Material Type Scale | Role | Default Size | Default Weight | Usage | |------|-------------|----------------|-------| | displayLarge | 57sp | 400 | Hero text, onboarding | | displayMedium | 45sp | 400 | Large feature text | | displaySmall | 36sp | 400 | Prominent display | | headlineLarge | 32sp | 400 | Screen titles | | headlineMedium | 28sp | 400 | Section headers | | headlineSmall | 24sp | 400 | Card titles | | titleLarge | 22sp | 400 | Top app bar title | | titleMedium | 16sp | 500 | Tabs, navigation | | titleSmall | 14sp | 500 | Subtitles | | bodyLarge | 16sp | 400 | Primary body text | | bodyMedium | 14sp | 400 | Secondary body text | | bodySmall | 12sp | 400 | Captions | | labelLarge | 14sp | 500 | Buttons, prominent labels | | labelMedium | 12sp | 500 | Chips, smaller labels | | labelSmall | 11sp | 500 | Timestamps, annotations |
GitHubで見る
この SKILL.md は非常に大きいため、SkillsMP では最初のセクションだけを表示しています。 GitHubで見る