How to change color only a fraction of the total in swift?

I'm doing a QR code scan. I use UIView to change the background color of the screen to translucent color. However, I want to make the background color of the place that scans the QR code transparent. What should I do?




class QRcodeScannerViewController : UIViewController, AVCaptureMetadataOutputObjectsDelegate {
   
    @IBOutlet weak var qrcodeView: UIView!
    @IBOutlet weak var header: UINavigationBar!
    @IBOutlet weak var flash: UIButton!
    @IBOutlet weak var qrcodeScanArea: UIImageView!
                   var previewLayer: AVCaptureVideoPreviewLayer!


    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.black
        self.qrcodeView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
        view.layer.insertSublayer(previewLayer, at: 0)
        view.bringSubviewToFront(flash)
        view.bringSubviewToFront(header)
        header.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
        header.isTranslucent = true
        header.backgroundColor = UIColor.clear
        header.shadowImage = UIImage()




Current My QRcode ScanView




Here's the view I want:



I tried many things. But it didn't work for me.

        view.addSubview(qrcodeView)
        let shape = CGRect(x: 0, y: 0, width: 200, height: 200)
        let maskLayer = CAShapeLayer()
        maskLayer.path = UIBezierPath(roundedRect: shape, cornerRadius: 0).cgPath
        maskLayer.backgroundColor = UIColor.clear.cgColor
        maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
        qrcodeView.layer.mask = maskLayer


The screen I tried.


I was made FocusView.swift


import Foundation

fileprivate let focusSize: CGSize = CGSize(width: 200, height: 200)

class FocusView: UIView {

    var areaBackground: UIColor? {
        set {
            maskedFocusView.backgroundColor = newValue
        }

        get {
            return maskedFocusView.backgroundColor
        }
    }

    fileprivate let maskedFocusView: MaskedFocusView = {
        return MaskedFocusView()
    }()

    let focusView: UIView = {
        let view = UIView()
        view.layer.borderColor = UIColor.white.cgColor
        view.layer.borderWidth = 2
        view.layer.masksToBounds = true
        return view
    }()

    override func awakeFromNib() {
        super.awakeFromNib()
        commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    func commonInit() {
        backgroundColor = UIColor.darkGray.withAlphaComponent(0.5)

        translatesAutoresizingMaskIntoConstraints = false
        maskedFocusView.layoutSubviews()
        addSubview(maskedFocusView)
        addSubview(focusView)
        setupFocusViewConstraints()
        setupMaskedFocusViewConstraints()
    }

    func setupFocusViewConstraints() {
        NSLayoutConstraint.activate(
            focusView.centerXAnchor.constraint(equalTo: centerXAnchor),
            focusView.centerYAnchor.constraint(equalTo: centerYAnchor)
        )

        let regularFocusViewConstraints = [
            focusView.widthAnchor.constraint(equalToConstant: focusSize.width),
            focusView.heightAnchor.constraint(equalToConstant: focusSize.height)
        ]

        NSLayoutConstraint.activate(regularFocusViewConstraints)
    }

    func setupMaskedFocusViewConstraints() {
        NSLayoutConstraint.activate(
            maskedFocusView.centerXAnchor.constraint(equalTo: centerXAnchor),
            maskedFocusView.centerYAnchor.constraint(equalTo: centerYAnchor),
            maskedFocusView.topAnchor.constraint(equalTo: topAnchor),
            maskedFocusView.bottomAnchor.constraint(equalTo: bottomAnchor),
            maskedFocusView.leadingAnchor.constraint(equalTo: leadingAnchor),
            maskedFocusView.trailingAnchor.constraint(equalTo: trailingAnchor)
        )
    }

}

// MARK: - Masked focus view

fileprivate class MaskedFocusView: UIView {

    let maskLayer: CAShapeLayer = CAShapeLayer()

    override func awakeFromNib() {
        super.awakeFromNib()
        commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    func commonInit() {
        backgroundColor = UIColor.darkGray.withAlphaComponent(0.5)

        maskLayer.backgroundColor = UIColor.clear.cgColor

        layer.mask = maskLayer

        translatesAutoresizingMaskIntoConstraints = false
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        let width = bounds.width
        let height = bounds.height

        let x = (width - focusSize.width) / 2
        let y = (height - focusSize.height) / 2

        let focusRect = CGRect(x: x, y: y, width: focusSize.width, height: focusSize.height)
        let fullRect = CGRect(origin: bounds.origin, size: bounds.size)

        let path = CGMutablePath()
        path.addPath(UIBezierPath(rect: fullRect).cgPath)
        path.addPath(UIBezierPath(roundedRect: focusRect, cornerRadius: 0).reversing().cgPath)

        maskLayer.path = path
        maskLayer.fillRule = .evenOdd
    }

}

// MARK: - Layout constraints extension

extension NSLayoutConstraint {
  /// A helper function to activate layout constraints.
  static func activate(_ constraints: NSLayoutConstraint? ...) {
    for case let constraint in constraints {
      guard let constraint = constraint else {
        continue
      }

      (constraint.firstItem as? UIView)?.translatesAutoresizingMaskIntoConstraints = false
      constraint.isActive = true
    }
  }
}

extension Array where Element: NSLayoutConstraint {
  func activate() {
    forEach {
      if !$0.isActive {
        $0.isActive = true
      }
    }
  }

  func deactivate() {
    forEach {
      if $0.isActive {
        $0.isActive = false
      }
    }
  }
}


and Usage


let focusview = FocusView.init(frame: qrcodeView.frame)
focusview.areaBackground = UIColor.black
view.addSubview(focusview)


The screen I tried