Swift Gradient Background Surrounding Text Vertically

Recently I wanted to have a screen that displayed text in the middle, with the text framed by a vertical gradient fading in and back out again. This post illustrates how it can be done in Swift.

Update 17 July 2017: Since I’m still waiting for a MacBook Pro with 32 GB of RAM, I decided to update the demo app to Swift 3. I did not update the code in this post, but you will see that the differences are minor!

I started out with a standard Single View Application, and added a UILabel to it, centered vertically and constrained to be 20 pixels from the leading and trailing margins.

For this example let’s assume that the label will contain the most recent tweet that you’ve posted. In the sample project, I won’t actually integrate with Twitter, but will just populate the UILabel in viewWillAppear, as follows:

If I run it now it looks quite boring, as you can see below.

Simulator Screen Shot Apr 5, 2016, 4.30.03 PM

To achieve the gradient effect, the IBOutlet for the UILabel and the CAGradientLayer declaration are added.

The initial gradient setup should be done in viewDidLoad, since it will be a one time setup that does not need to be updated.

What I’ve defined in setupGradient is a gradient with 4 color stops. The reason there are 4 is so that the gradient can start out blue, fade into white, remain white until the bottom of the UILabel with the text, and then transition back to blue at the bottom of the screen. The gradient is added to the view as a sublayer.

Now we proceed to handling the portion of the gradient that is dependent on the frame size/bounds and orientation of the device.

The first method is to override viewDidLayoutSubviews, which is where updating the gradient will be triggered from. It is triggered here versus viewWillAppear because viewDidLayoutSubviews is the method that is called when the bounds change for a view controller’€™s view, and the view has adjusted the positions of its subviews.

You’ll note that unlike with viewWillAppear and viewDidLoad, I’ve not called super in viewDidLayoutSubviews, since the default implementation does nothing. Two more methods complete the code for this project.

The updateGradient method sets the frame of the gradient to match view.bounds, and then the gradient locations are determined via the gradientLocations method. I’ve added comments in the code to describe how the middle two gradient stops  are calculated.

With the code in place, running in the simulator results in the screen below for portrait. When switching between portrait and landscape, the gradient is updated accordingly because rotation causes viewDidLayoutSubviews to be called.

Simulator Screen Shot Apr 5, 2016, 4.45.42 PM

The code for this project is in GitHub here. Comments are welcome if you have feedback or suggestions.

Leave a Comment: