Fading View Content in UIKit

Fading content, especially when it's inside a scroll view, is a useful trick when you want to avoid a separator. Instead, sometimes it's much nicer to make the content gradually disappear as it is nearing an edge of another view – such as navigation bar – or a screen edge. It used to be quite popular before, mostly in the skeumorphism era, but now I see it sometimes too. How can we achieve this?

The simplest solution has always been adding a CAGradientLayer that would transition from clear color to your background color near the edge of the view.

let gradient = CAGradientLayer() 
gradient.colors = [
    UIColor.myBackgroundColor.cgColor, 
    UIColor.myBackgroundColor.withAlphaComponent(0.0).cgColor
]
gradient.startPoint = CGPoint(x: 0.0, y: 0.5) 
gradient.endPoint = CGPoint(x: 1, y: 0.5)

But this approach has a limitation – it works only if your view has a solid background. If it becomes dynamic, blurred or just multi-color, it's impossible to make the gradient work. Today, for example, toolbars on iOS are translucent, and if you want to fade something there, this simple approach won't work.

Luckily, there is a simple technique that helps here. It's one of those hidden gems of UIKit × CoreAnimation collaboration that let us do nice visual tricks. It's called layer masking. This approach allows us to provide a mask to a view's CALayer that will be used to blend its subviews accordingly during rendering. The key thing here is that the mask can be any CALayer, and in our case we need CAGradientLayer with semi-transparent colors.

gradientLayer.colors = [
    UIColor.clear.cgColor, 
    UIColor.white.cgColor, 
    UIColor.white.cgColor, 
    UIColor.clear.cgColor
]
gradientLayer.locations = [0.0, 0.25, 0.75, 1.0]
gradientLayer.frame = view.bounds
view.layer.mask = gradientLayer

I provided a sample code and created a UIView subclass that can be used to apply this effect to any view: https://github.com/pavelshadrin/fadingblur. Here is the result how text is faded at the horizontal edges on top of multiple backgrounds:

What's good about this technique, it is pretty flexible in what can be done with it – for example, you can do radial gradient to have something similar to the vignette effect, or you can use layer masking to achieve basically any shape for your views.

Happy Swift coding!