In this post, we will breakdown and analyze the Now Playing screen of Spotify app, and try to replicate it using Auto Layout. This post assume you have some experience working with Auto Layout.

The playback button icons used in this post are from Font Awesome, you can use fa2png.io to generate png images from the font awesome icons.

Here's the Now Playing screen of Spotify viewed in iPhone 8 screen size:

Spotify UI

The scrollable album art is a collection view, song name and artist name are labels, there's five button (shuffle, previous, play/pause, next, repeat), the song progress bar is a slider. The left two and right two buttons are grouped in stack views, this will be explained more later.

Spotify UI Analyze

The vertical distance of each UI elements are shown using the blue arrow. Feel free to tweak the value of the vertical constraint until it feels right for you.


Album Art Collection View

Let's say each album art is a collection view cell itself, each cell is a square , meaning its width is equal to height, this means a ratio of 1:1 .

Collection Cell

To make it simple, assume the collection view containing the cell has the same height as the cell itself, with same width but with added spacing on the left (34 pt) and right (34 pt). This means the collection view has an aspect ratio of 1:1 + 34 +34 = 1:1 + 68.

Collection View

1 * width = 1 * height + 34 +34
width = height + 68
height = width - 68

The collection view has a top constraint to the top edge of safe area, leading constraint with value 0, trailing constraint with value 0. The leading and trailing constraint means that the collection view's width is equal to the screen width.

Since there are distances from the album art to the screen edge (left and right), and the album art is a square, the height of the collection view will be 68 pt lesser than its width.

We can set a ratio constraint on the collection view like this :

Aspect ratio constraint

Aspect Ratio 2

In the attribute inspector, set the scrolling direction of the collection view to horizontal.
Horizontal direction

Set the collection view's background color to "Clear color" so it will be transparent. This is needed when we do the fading effect of the album art image in the next part.

Album Art Collection View Cell

After creating the collection view, drag a collection view cell into the collection view if there isn't one already :

Collection View Cell

Set the collection view cell's background color to "Clear color" so it will be transparent. This is needed when we do the fading effect of the album art image in the next part. We will also set a reuse identifier for the cell so we can reuse it in code in the next part.

Cell Attributes

After that, drag an image view into the cell and add constraints to make the image has the same size as the cell. Create a top, leading, trailing and bottom constraints with value 0 for the image view.

Cell Image Constraint

Next, set the imageview's image to your favorite album art picture! 😆

Play button

Say you are using the play button from Font Awesome like this :

Play button

To make it simple, we set a fixed width (74pt) and height (74pt) for the Play button and center it horizontally to the parent view.

To add a surrounding circle to the play button, we can use the cornerRadius and borderWidth property of the button's layer.

// the circle around the play button
playButton.layer.cornerRadius = playButton.frame.size.height / 2.0
playButton.layer.borderWidth = 2.0
playButton.layer.borderColor = UIColor.white.cgColor

Hmmm, now the play button image seems too big and too close to the surrounding circle :
too big

We can adjust the Image Insets of the button in Size inspector tab to add padding to the image :
Image insets

The image insets means the spacing from the image to the button edge. With the above values, we will set 20 pt padding on top, left, bottom and right for the image inside button.

After adding insets, the play button looks better now with padding :

circled play button

Playback buttons and stack view

The play button is located in the center (using the align horizontal center constraint), and there's other buttons beside it. At first glance, using fixed leading / trailing constraint between each button seems to do the job :

Spacing between buttons

These constraints looks fine on an iPhone SE screen size, but when viewed on iPhone 8 plus, the left and right edge of the screen feels empty as it have too much blank space.

Extra spacing

To reduce the blank space, we will have to distribute the button evenly, meaning they occupy a certain proportion of the width of the screen size. As the screen width increase, they should occupy more width so that there wouldn't be a chunk of blank space.

To distribute button evenly, we can use a stack view and set its Distribution property to Fill Equally. Then we place placeholder views inside the stackview and each of the placeholder view has the same width. Next we place the button inside the placeholder view, and horizontally center the button to the placeholder view.

Stack view

Repeat this process for the left part (shuffle and previous buttons). Now you should have an evenly distributed buttons. But you might find the image on the button stretches, this is because the content mode of image inside a button is "Scale to Fill" by default. To resolve the stretching issue, we can set the content mode to "Aspect Fit" using code :

// make the image on these button become aspect fit so it won't stretch
shuffleButton.imageView?.contentMode = .scaleAspectFit
previousButton.imageView?.contentMode = .scaleAspectFit
forwardButton.imageView?.contentMode = .scaleAspectFit
repeatButton.imageView?.contentMode = .scaleAspectFit

This is how the playback buttons looks like in iPhone SE and iPhone 8 plus using stack view:

Evenly distributed buttons

Progress Slider

A default slider looks like this:
default slider

You can customize the left bar color and right bar color with the Min Track and Max track color property.

minMax Color

As the default circle size is too large for the song progress slider, we can replace it with a smaller circle (the circle is called as "Thumb"). You will need to prepare an image containing a smaller circle for this.

// set image for the button of the slider, when not selected, its small
progressSlider.setThumbImage(UIImage(named: "sliderThumb"), for: .normal)

If you have noticed, when you are selecting the slider in Spotify, the thumb become larger and has another layer of half-transparent circle around it.

selectedStateSlider

The easiest way to replicate this is to prepare an image for it. And set a different thumb image for the selected state.

// when selected, use a larger image
progressSlider.setThumbImage(UIImage(named: "sliderThumbSelected"), for: .highlighted)

Current result

Part 1 Result

It kinda looks good now! Just that the collection view cell doesn't have spacing and doesn't have the zooming / fade out effect when scrolled. We will add these effect into the collection view in part 2.