What You Will Build
A dark-themed control center panel with toggle icons arranged in a grid row, plus a now-playing music card, replicating the iOS Control Center aesthetic. This pattern is useful for quick-settings panels, smart home dashboards, or any app with toggleable system controls.
Why This Pattern Matters
Building a control panel teaches you how to arrange circular icon buttons in a row, apply translucent dark card backgrounds, and create a cohesive dark-themed interface. These skills transfer directly to building settings screens, dashboards, and widget-style interfaces.
Key Concepts
- Dark color palette with explicit hex colors for a custom dark theme.
- forEach with list of pairs to generate toggle button rows dynamically.
- CircleShape clips for circular icon containers with translucent backgrounds.
The Control Center Screen
@Composable
fun IosControlCenterScreen() {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color(0xFF0A0A0A))
.padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(Modifier.height(40.dp))
Text("iOS Control Center",
color = Color.White,
fontWeight = FontWeight.Bold,
fontSize = 22.sp)
Spacer(Modifier.height(32.dp))
// Toggle widgets card
Card(
Modifier.fillMaxWidth(),
shape = RoundedCornerShape(20.dp),
colors = CardDefaults.cardColors(
containerColor = Color(0xFF1A1A2E)
)
) {
Column(Modifier.padding(20.dp)) {
Row(
Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text("Widget Preview",
color = Color.White,
fontWeight = FontWeight.Bold)
Text("12:00",
color = Color.White.copy(alpha = 0.6f))
}
Spacer(Modifier.height(12.dp))
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
listOf(
"Wifi" to Icons.Default.Wifi,
"BT" to Icons.Default.Bluetooth,
"GPS" to Icons.Default.LocationOn,
"NFC" to Icons.Default.Nfc
).forEach { (label, icon) ->
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
Modifier
.size(48.dp)
.clip(CircleShape)
.background(Color.White.copy(alpha = 0.1f)),
contentAlignment = Alignment.Center
) {
Icon(icon, null,
tint = Color(0xFF64B5F6))
}
Text(label, fontSize = 10.sp,
color = Color.White.copy(alpha = 0.6f))
}
}
}
}
}
Spacer(Modifier.height(16.dp))
// Now Playing card
Card(
Modifier.fillMaxWidth(),
shape = RoundedCornerShape(16.dp),
colors = CardDefaults.cardColors(
containerColor = Color(0xFF1A1A2E)
)
) {
Row(
Modifier.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(Icons.Default.MusicNote, null,
tint = Color(0xFF4CAF50))
Spacer(Modifier.width(12.dp))
Column(Modifier.weight(1f)) {
Text("Now Playing",
color = Color.White,
fontWeight = FontWeight.SemiBold)
Text("Song Title - Artist",
color = Color.White.copy(alpha = 0.6f),
fontSize = 13.sp)
}
Icon(Icons.Default.PlayArrow, null,
tint = Color.White)
}
}
}
}
Tips and Pitfalls
- Custom dark backgrounds: Using
Color(0xFF0A0A0A)gives a deeper black than MaterialTheme dark colors, matching the iOS aesthetic. - Translucent overlays:
Color.White.copy(alpha = 0.1f)creates the glass-like button backgrounds without requiring blur effects. - Toggle state: Add
mutableStateOf(false)for each toggle and change the icon tint to indicate active/inactive states. - Haptic feedback: Call
view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY)on toggle taps for a native feel.
Minimum SDK: API 21+ with Compose BOM