How to get multiply blend mode on a plain UIView (not UIImage)
Take a look at the docs for CALayer's compositingFilter: https://developer.apple.com/documentation/quartzcore/calayer/1410748-compositingfilter
On your color overlay view you can set view.layer.compositingFilter
to a CICategoryCompositeOperation to achieve blending with the content behind it. Here is some sample playground code with a multiply blend mode applied to test it out (replace the UIImage(named: "")
with your own image for testing)
import UIKitimport PlaygroundSupportclass MyViewController : UIViewController { override func loadView() { let mainView = UIView() self.view = mainView let image = UIImageView() image.translatesAutoresizingMaskIntoConstraints = false; image.image = UIImage(named: "maxresdefault.jpg") mainView.addSubview(image) let overlay = UIView() overlay.translatesAutoresizingMaskIntoConstraints = false; overlay.backgroundColor = .red overlay.layer.compositingFilter = "multiplyBlendMode" mainView.addSubview(overlay) mainView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": view])) mainView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": view])) mainView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": overlay])) mainView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": overlay])) }}PlaygroundPage.current.liveView = MyViewController()
iOS 13, Swift 5
The key is setting the compositingFilter
property on the appropriate CALayer (the one on top - it blends with whatever is behind it). Color blending works between UIViews or CALayers. You can find blending modes here CICategoryCompositeOperation. To use a filter, just drop the CI
& lowercase the first letter of the name (e.g. CIDivideBlendMode
becomes divideBlendMode
). Here is some playground code to illustrate:
import UIKitimport PlaygroundSupportlet view = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 900))PlaygroundPage.current.liveView = viewlet heightIncrement = view.frame.height / 13let widthIncrement = view.frame.width / 7// TOP EXAMPLE (UIViews)let backgroundView = UIView(frame: CGRect(x: widthIncrement * 2, y: heightIncrement, width: widthIncrement * 3, height: heightIncrement * 5))backgroundView.backgroundColor = .blackview.addSubview(backgroundView)let overlayView1 = UIView(frame: CGRect(x: widthIncrement, y: heightIncrement * 2, width: widthIncrement * 5, height: heightIncrement))overlayView1.backgroundColor = UIColor.yellow.withAlphaComponent(0.3)overlayView1.layer.compositingFilter = "darkenBlendMode"view.addSubview(overlayView1)let overlayView2 = UIView(frame: CGRect(x: widthIncrement, y: heightIncrement * 4, width: widthIncrement * 5, height: heightIncrement))overlayView2.backgroundColor = UIColor.yellow.withAlphaComponent(0.3)overlayView2.layer.compositingFilter = "divideBlendMode"view.addSubview(overlayView2)// BOTTOM EXAMPLE (CALayers)let backgroundLayer = CALayer()backgroundLayer.frame = CGRect(x: widthIncrement * 2, y: heightIncrement * 7, width: widthIncrement * 3, height: heightIncrement * 5)backgroundLayer.backgroundColor = UIColor.black.cgColorview.layer.addSublayer(backgroundLayer)let overlayLayer1 = CALayer()overlayLayer1.frame = CGRect(x: widthIncrement, y: heightIncrement * 8, width: widthIncrement * 5, height: heightIncrement)overlayLayer1.backgroundColor = UIColor.yellow.withAlphaComponent(0.3).cgColoroverlayLayer1.compositingFilter = "darkenBlendMode"view.layer.addSublayer(overlayLayer1)let overlayLayer2 = CALayer()overlayLayer2.frame = CGRect(x: widthIncrement, y: heightIncrement * 10, width: widthIncrement * 5, height: heightIncrement)overlayLayer2.backgroundColor = UIColor.yellow.withAlphaComponent(0.3).cgColoroverlayLayer2.compositingFilter = "divideBlendMode"view.layer.addSublayer(overlayLayer2)
The result looks like this:
I confirmed that the same code works in iOS. Here's the view controller code:
import UIKitclass ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let heightIncrement = view.frame.height / 13 let widthIncrement = view.frame.width / 7 // TOP EXAMPLE (UIViews) let backgroundView = UIView(frame: CGRect(x: widthIncrement * 2, y: heightIncrement, width: widthIncrement * 3, height: heightIncrement * 5)) backgroundView.backgroundColor = .black view.addSubview(backgroundView) let overlayView1 = UIView(frame: CGRect(x: widthIncrement, y: heightIncrement * 2, width: widthIncrement * 5, height: heightIncrement)) overlayView1.backgroundColor = UIColor.yellow.withAlphaComponent(0.3) overlayView1.layer.compositingFilter = "darkenBlendMode" view.addSubview(overlayView1) let overlayView2 = UIView(frame: CGRect(x: widthIncrement, y: heightIncrement * 4, width: widthIncrement * 5, height: heightIncrement)) overlayView2.backgroundColor = UIColor.yellow.withAlphaComponent(0.3) overlayView2.layer.compositingFilter = "divideBlendMode" view.addSubview(overlayView2) // BOTTOM EXAMPLE (CALayers) let backgroundLayer = CALayer() backgroundLayer.frame = CGRect(x: widthIncrement * 2, y: heightIncrement * 7, width: widthIncrement * 3, height: heightIncrement * 5) backgroundLayer.backgroundColor = UIColor.black.cgColor view.layer.addSublayer(backgroundLayer) let overlayLayer1 = CALayer() overlayLayer1.frame = CGRect(x: widthIncrement, y: heightIncrement * 8, width: widthIncrement * 5, height: heightIncrement) overlayLayer1.backgroundColor = UIColor.yellow.withAlphaComponent(0.3).cgColor overlayLayer1.compositingFilter = "darkenBlendMode" view.layer.addSublayer(overlayLayer1) let overlayLayer2 = CALayer() overlayLayer2.frame = CGRect(x: widthIncrement, y: heightIncrement * 10, width: widthIncrement * 5, height: heightIncrement) overlayLayer2.backgroundColor = UIColor.yellow.withAlphaComponent(0.3).cgColor overlayLayer2.compositingFilter = "divideBlendMode" view.layer.addSublayer(overlayLayer2) }}
And here's the result in the simulator: