Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    wshobson

    mobile-android-design

    wshobson/mobile-android-design
    Design
    28,185
    8 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Master Material Design 3 and Jetpack Compose patterns for building native Android apps...

    SKILL.md

    Android Mobile Design

    Master Material Design 3 (Material You) and Jetpack Compose to build modern, adaptive Android applications that integrate seamlessly with the Android ecosystem.

    When to Use This Skill

    • Designing Android app interfaces following Material Design 3
    • Building Jetpack Compose UI and layouts
    • Implementing Android navigation patterns (Navigation Compose)
    • Creating adaptive layouts for phones, tablets, and foldables
    • Using Material 3 theming with dynamic colors
    • Building accessible Android interfaces
    • Implementing Android-specific gestures and interactions
    • Designing for different screen configurations

    Core Concepts

    1. Material Design 3 Principles

    Personalization: Dynamic color adapts UI to user's wallpaper Accessibility: Tonal palettes ensure sufficient color contrast Large Screens: Responsive layouts for tablets and foldables

    Material Components:

    • Cards, Buttons, FABs, Chips
    • Navigation (rail, drawer, bottom nav)
    • Text fields, Dialogs, Sheets
    • Lists, Menus, Progress indicators

    2. Jetpack Compose Layout System

    Column and Row:

    // Vertical arrangement with alignment
    Column(
        modifier = Modifier.padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp),
        horizontalAlignment = Alignment.Start
    ) {
        Text(
            text = "Title",
            style = MaterialTheme.typography.headlineSmall
        )
        Text(
            text = "Subtitle",
            style = MaterialTheme.typography.bodyMedium,
            color = MaterialTheme.colorScheme.onSurfaceVariant
        )
    }
    
    // Horizontal arrangement with weight
    Row(
        modifier = Modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.SpaceBetween,
        verticalAlignment = Alignment.CenterVertically
    ) {
        Icon(Icons.Default.Star, contentDescription = null)
        Text("Featured")
        Spacer(modifier = Modifier.weight(1f))
        TextButton(onClick = {}) {
            Text("View All")
        }
    }
    

    Lazy Lists and Grids:

    // Lazy column with sticky headers
    LazyColumn {
        items.groupBy { it.category }.forEach { (category, categoryItems) ->
            stickyHeader {
                Text(
                    text = category,
                    modifier = Modifier
                        .fillMaxWidth()
                        .background(MaterialTheme.colorScheme.surface)
                        .padding(16.dp),
                    style = MaterialTheme.typography.titleMedium
                )
            }
            items(categoryItems) { item ->
                ItemRow(item = item)
            }
        }
    }
    
    // Adaptive grid
    LazyVerticalGrid(
        columns = GridCells.Adaptive(minSize = 150.dp),
        contentPadding = PaddingValues(16.dp),
        horizontalArrangement = Arrangement.spacedBy(12.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        items(items) { item ->
            ItemCard(item = item)
        }
    }
    

    3. Navigation Patterns

    Bottom Navigation:

    @Composable
    fun MainScreen() {
        val navController = rememberNavController()
    
        Scaffold(
            bottomBar = {
                NavigationBar {
                    val navBackStackEntry by navController.currentBackStackEntryAsState()
                    val currentDestination = navBackStackEntry?.destination
    
                    NavigationDestination.entries.forEach { destination ->
                        NavigationBarItem(
                            icon = { Icon(destination.icon, contentDescription = null) },
                            label = { Text(destination.label) },
                            selected = currentDestination?.hierarchy?.any {
                                it.route == destination.route
                            } == true,
                            onClick = {
                                navController.navigate(destination.route) {
                                    popUpTo(navController.graph.findStartDestination().id) {
                                        saveState = true
                                    }
                                    launchSingleTop = true
                                    restoreState = true
                                }
                            }
                        )
                    }
                }
            }
        ) { innerPadding ->
            NavHost(
                navController = navController,
                startDestination = NavigationDestination.Home.route,
                modifier = Modifier.padding(innerPadding)
            ) {
                composable(NavigationDestination.Home.route) { HomeScreen() }
                composable(NavigationDestination.Search.route) { SearchScreen() }
                composable(NavigationDestination.Profile.route) { ProfileScreen() }
            }
        }
    }
    

    Navigation Drawer:

    @Composable
    fun DrawerNavigation() {
        val drawerState = rememberDrawerState(DrawerValue.Closed)
        val scope = rememberCoroutineScope()
    
        ModalNavigationDrawer(
            drawerState = drawerState,
            drawerContent = {
                ModalDrawerSheet {
                    Spacer(Modifier.height(12.dp))
                    Text(
                        "App Name",
                        modifier = Modifier.padding(16.dp),
                        style = MaterialTheme.typography.titleLarge
                    )
                    HorizontalDivider()
    
                    NavigationDrawerItem(
                        icon = { Icon(Icons.Default.Home, null) },
                        label = { Text("Home") },
                        selected = true,
                        onClick = { scope.launch { drawerState.close() } }
                    )
                    NavigationDrawerItem(
                        icon = { Icon(Icons.Default.Settings, null) },
                        label = { Text("Settings") },
                        selected = false,
                        onClick = { }
                    )
                }
            }
        ) {
            Scaffold(
                topBar = {
                    TopAppBar(
                        title = { Text("Home") },
                        navigationIcon = {
                            IconButton(onClick = { scope.launch { drawerState.open() } }) {
                                Icon(Icons.Default.Menu, contentDescription = "Menu")
                            }
                        }
                    )
                }
            ) { innerPadding ->
                Content(modifier = Modifier.padding(innerPadding))
            }
        }
    }
    

    4. Material 3 Theming

    Color Scheme:

    // Dynamic color (Android 12+)
    val dynamicColorScheme = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        val context = LocalContext.current
        if (darkTheme) dynamicDarkColorScheme(context)
        else dynamicLightColorScheme(context)
    } else {
        if (darkTheme) DarkColorScheme else LightColorScheme
    }
    
    // Custom color scheme
    private val LightColorScheme = lightColorScheme(
        primary = Color(0xFF6750A4),
        onPrimary = Color.White,
        primaryContainer = Color(0xFFEADDFF),
        onPrimaryContainer = Color(0xFF21005D),
        secondary = Color(0xFF625B71),
        onSecondary = Color.White,
        tertiary = Color(0xFF7D5260),
        onTertiary = Color.White,
        surface = Color(0xFFFFFBFE),
        onSurface = Color(0xFF1C1B1F),
    )
    

    Typography:

    val AppTypography = Typography(
        displayLarge = TextStyle(
            fontFamily = FontFamily.Default,
            fontWeight = FontWeight.Normal,
            fontSize = 57.sp,
            lineHeight = 64.sp
        ),
        headlineMedium = TextStyle(
            fontFamily = FontFamily.Default,
            fontWeight = FontWeight.Normal,
            fontSize = 28.sp,
            lineHeight = 36.sp
        ),
        titleLarge = TextStyle(
            fontFamily = FontFamily.Default,
            fontWeight = FontWeight.Normal,
            fontSize = 22.sp,
            lineHeight = 28.sp
        ),
        bodyLarge = TextStyle(
            fontFamily = FontFamily.Default,
            fontWeight = FontWeight.Normal,
            fontSize = 16.sp,
            lineHeight = 24.sp
        ),
        labelMedium = TextStyle(
            fontFamily = FontFamily.Default,
            fontWeight = FontWeight.Medium,
            fontSize = 12.sp,
            lineHeight = 16.sp
        )
    )
    

    5. Component Examples

    Cards:

    @Composable
    fun FeatureCard(
        title: String,
        description: String,
        imageUrl: String,
        onClick: () -> Unit
    ) {
        Card(
            onClick = onClick,
            modifier = Modifier.fillMaxWidth(),
            shape = RoundedCornerShape(16.dp),
            colors = CardDefaults.cardColors(
                containerColor = MaterialTheme.colorScheme.surfaceVariant
            )
        ) {
            Column {
                AsyncImage(
                    model = imageUrl,
                    contentDescription = null,
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(180.dp),
                    contentScale = ContentScale.Crop
                )
                Column(modifier = Modifier.padding(16.dp)) {
                    Text(
                        text = title,
                        style = MaterialTheme.typography.titleMedium
                    )
                    Spacer(modifier = Modifier.height(8.dp))
                    Text(
                        text = description,
                        style = MaterialTheme.typography.bodyMedium,
                        color = MaterialTheme.colorScheme.onSurfaceVariant
                    )
                }
            }
        }
    }
    

    Buttons:

    // Filled button (primary action)
    Button(onClick = { }) {
        Text("Continue")
    }
    
    // Filled tonal button (secondary action)
    FilledTonalButton(onClick = { }) {
        Icon(Icons.Default.Add, null)
        Spacer(Modifier.width(8.dp))
        Text("Add Item")
    }
    
    // Outlined button
    OutlinedButton(onClick = { }) {
        Text("Cancel")
    }
    
    // Text button
    TextButton(onClick = { }) {
        Text("Learn More")
    }
    
    // FAB
    FloatingActionButton(
        onClick = { },
        containerColor = MaterialTheme.colorScheme.primaryContainer,
        contentColor = MaterialTheme.colorScheme.onPrimaryContainer
    ) {
        Icon(Icons.Default.Add, contentDescription = "Add")
    }
    

    Quick Start Component

    @Composable
    fun ItemListCard(
        item: Item,
        onItemClick: () -> Unit,
        modifier: Modifier = Modifier
    ) {
        Card(
            onClick = onItemClick,
            modifier = modifier.fillMaxWidth(),
            shape = RoundedCornerShape(12.dp)
        ) {
            Row(
                modifier = Modifier
                    .padding(16.dp)
                    .fillMaxWidth(),
                verticalAlignment = Alignment.CenterVertically
            ) {
                Box(
                    modifier = Modifier
                        .size(48.dp)
                        .clip(CircleShape)
                        .background(MaterialTheme.colorScheme.primaryContainer),
                    contentAlignment = Alignment.Center
                ) {
                    Icon(
                        imageVector = Icons.Default.Star,
                        contentDescription = null,
                        tint = MaterialTheme.colorScheme.onPrimaryContainer
                    )
                }
    
                Spacer(modifier = Modifier.width(16.dp))
    
                Column(modifier = Modifier.weight(1f)) {
                    Text(
                        text = item.title,
                        style = MaterialTheme.typography.titleMedium
                    )
                    Text(
                        text = item.subtitle,
                        style = MaterialTheme.typography.bodyMedium,
                        color = MaterialTheme.colorScheme.onSurfaceVariant
                    )
                }
    
                Icon(
                    imageVector = Icons.Default.ChevronRight,
                    contentDescription = null,
                    tint = MaterialTheme.colorScheme.onSurfaceVariant
                )
            }
        }
    }
    

    Best Practices

    1. Use Material Theme: Access colors via MaterialTheme.colorScheme for automatic dark mode support
    2. Support Dynamic Color: Enable dynamic color on Android 12+ for personalization
    3. Adaptive Layouts: Use WindowSizeClass for responsive designs
    4. Content Descriptions: Add contentDescription to all interactive elements
    5. Touch Targets: Minimum 48dp touch targets for accessibility
    6. State Hoisting: Hoist state to make components reusable and testable
    7. Remember Properly: Use remember and rememberSaveable appropriately
    8. Preview Annotations: Add @Preview with different configurations

    Common Issues

    • Recomposition Issues: Avoid passing unstable lambdas; use remember
    • State Loss: Use rememberSaveable for configuration changes
    • Performance: Use LazyColumn instead of Column for long lists
    • Theme Leaks: Ensure MaterialTheme wraps all composables
    • Navigation Crashes: Handle back press and deep links properly
    • Memory Leaks: Cancel coroutines in DisposableEffect
    Recommended Servers
    InstantDB
    InstantDB
    Vercel Grep
    Vercel Grep
    tldraw
    tldraw
    Repository
    wshobson/agents
    Files