Claude Agent Skill · by Wshobson

Mobile Android Design

A solid foundation for Android UI development that covers Material Design 3 patterns and Jetpack Compose layouts. It walks you through building navigation drawe

Install
Terminal · npx
$npx skills add https://github.com/wshobson/agents --skill mobile-android-design
Works with Paperclip

How Mobile Android Design fits into a Paperclip company.

Mobile Android Design drops into any Paperclip agent that handles this kind of work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.

S
SaaS FactoryPaired

Pre-configured AI company — 18 agents, 18 skills, one-time purchase.

$27$59
Explore pack
Source file
SKILL.md433 lines
Expand
---name: mobile-android-designdescription: Master Material Design 3 and Jetpack Compose patterns for building native Android apps. Use when designing Android interfaces, implementing Compose UI, or following Google's Material Design guidelines.--- # 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:** ```kotlin// Vertical arrangement with alignmentColumn(    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 weightRow(    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:** ```kotlin// Lazy column with sticky headersLazyColumn {    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 gridLazyVerticalGrid(    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:** ```kotlin@Composablefun 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:** ```kotlin@Composablefun 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:** ```kotlin// 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 schemeprivate 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:** ```kotlinval 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:** ```kotlin@Composablefun 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:** ```kotlin// 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 buttonOutlinedButton(onClick = { }) {    Text("Cancel")} // Text buttonTextButton(onClick = { }) {    Text("Learn More")} // FABFloatingActionButton(    onClick = { },    containerColor = MaterialTheme.colorScheme.primaryContainer,    contentColor = MaterialTheme.colorScheme.onPrimaryContainer) {    Icon(Icons.Default.Add, contentDescription = "Add")}``` ## Quick Start Component ```kotlin@Composablefun 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 support2. **Support Dynamic Color**: Enable dynamic color on Android 12+ for personalization3. **Adaptive Layouts**: Use `WindowSizeClass` for responsive designs4. **Content Descriptions**: Add `contentDescription` to all interactive elements5. **Touch Targets**: Minimum 48dp touch targets for accessibility6. **State Hoisting**: Hoist state to make components reusable and testable7. **Remember Properly**: Use `remember` and `rememberSaveable` appropriately8. **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`