What You Will Build
A full-screen music player with a gradient background, album art placeholder, song title and artist, a seekbar slider, and playback controls (previous, play/pause, next). The play/pause button toggles state with a filled icon button.
Why This Pattern Matters
Music player UIs teach vertical gradient backgrounds, Slider customization, icon state toggling, and centered column layouts — patterns used in podcast apps, audiobook players, and media controls.
Step 1: Gradient Background
Column(
modifier = Modifier
.fillMaxSize()
.background(
Brush.verticalGradient(
listOf(Color(0xFF1A1A2E), Color(0xFF16213E))
)
)
.padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
// Content here
}
Step 2: Album Art Card
Card(
Modifier.size(280.dp),
shape = RoundedCornerShape(20.dp)
) {
Box(
Modifier.fillMaxSize()
.background(
Brush.linearGradient(
listOf(Color(0xFF6C63FF), Color(0xFFFF6584))
)
),
contentAlignment = Alignment.Center
) {
Icon(Icons.Default.MusicNote, null,
modifier = Modifier.size(80.dp), tint = Color.White)
}
}
Step 3: Seekbar and Controls
var isPlaying by remember { mutableStateOf(false) }
var progress by remember { mutableFloatStateOf(0.3f) }
// Song info
Text("Summer Vibes", color = Color.White,
fontSize = 24.sp, fontWeight = FontWeight.Bold)
Text("Artist Name", color = Color.White.copy(alpha = 0.7f))
// Seekbar
Slider(
value = progress,
onValueChange = { progress = it },
colors = SliderDefaults.colors(
thumbColor = Color.White,
activeTrackColor = Color(0xFF6C63FF)
)
)
Row(Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween) {
Text("1:15", color = Color.White.copy(alpha = 0.5f))
Text("3:45", color = Color.White.copy(alpha = 0.5f))
}
// Playback controls
Row(
horizontalArrangement = Arrangement.spacedBy(24.dp),
verticalAlignment = Alignment.CenterVertically
) {
IconButton(onClick = {}) {
Icon(Icons.Default.SkipPrevious, "Previous",
tint = Color.White, modifier = Modifier.size(36.dp))
}
FilledIconButton(
onClick = { isPlaying = !isPlaying },
modifier = Modifier.size(64.dp)
) {
Icon(
if (isPlaying) Icons.Default.Pause
else Icons.Default.PlayArrow,
"Play/Pause", modifier = Modifier.size(36.dp)
)
}
IconButton(onClick = {}) {
Icon(Icons.Default.SkipNext, "Next",
tint = Color.White, modifier = Modifier.size(36.dp))
}
}
Tips and Pitfalls
- Brush.verticalGradient creates the dark atmospheric background. Two similar dark colors create depth without distraction.
- SliderDefaults.colors lets you customize thumb and track colors to match your theme.
- FilledIconButton for play/pause makes it stand out as the primary action. Standard IconButton for secondary actions (skip).
- Real app extension: Connect to ExoPlayer and update the slider with
LaunchedEffectpolling current position.