Lal Krishna
Lal Krishna

Reputation: 16180

Custom View Drawing - Hole inside a View

How to draw View like this.

After research I got context.fillRects method can be used. But how to find the exact rects for this.

let context = UIGraphicsGetCurrentContext()
context?.setFillColor(UIColor.red.cgColor)
context?.setAlpha(0.5)
context?.fill([<#T##rects: [CGRect]##[CGRect]#>])

How to achieve this result?

enter image description here

Background: Blue.

Overlay(Purple): 50% opacity that contains square hole in the center

Upvotes: 0

Views: 542

Answers (3)

Lal Krishna
Lal Krishna

Reputation: 16180

I just ended up with this.

enter image description here

Code:

createHoleOnView()
let blurView = createBlurEffect(style: style)
self.addSubview(blurView)

Method Create Hole:

private func createHoleOnView() {

        let maskView = UIView(frame: self.frame)
        maskView.clipsToBounds = true;
        maskView.backgroundColor = UIColor.clear

        func holeRect() -> CGRect {
            var holeRect = CGRect(x: 0, y: 0, width: scanViewSize.rawValue.width, height: scanViewSize.rawValue.height)
            let midX = holeRect.midX
            let midY = holeRect.midY
            holeRect.origin.x = maskView.frame.midX - midX
            holeRect.origin.y = maskView.frame.midY - midY
            self.holeRect = holeRect
            return holeRect
        }

        let outerbezierPath = UIBezierPath.init(roundedRect: self.bounds, cornerRadius: 0)

        let holePath = UIBezierPath(roundedRect: holeRect(), cornerRadius: holeCornerRadius)
        outerbezierPath.append(holePath)
        outerbezierPath.usesEvenOddFillRule = true

        let hollowedLayer = CAShapeLayer()
        hollowedLayer.fillRule = kCAFillRuleEvenOdd
        hollowedLayer.fillColor = outerColor.cgColor
        hollowedLayer.path = outerbezierPath.cgPath

        if self.holeStyle == .none {
            hollowedLayer.opacity = 0.8
        }
        maskView.layer.addSublayer(hollowedLayer)

        switch self.holeStyle {
        case .none:
            self.addSubview(maskView)
            break

        case .blur(_):
            self.mask = maskView;
            break
        }
    }

UIView's Extension function for Create Blur:

internal func createBlurEffect(style: UIBlurEffectStyle = .extraLight) -> UIView {
    let blurEffect = UIBlurEffect(style: style)
    let blurEffectView = UIVisualEffectView(effect: blurEffect)
    blurEffectView.frame = self.bounds
    return blurEffectView
}

Upvotes: 0

Ocunidee
Ocunidee

Reputation: 1809

First create your view and then draw everything with two UIBezierPaths: one is describing the inside rect (the hole) and the other one runs along the borders on your screen (externalPath). This way of drawing ensures that the blue rect in the middle is a true hole and not drawn on top of the purple view.

let holeWidth: CGFloat = 200

let hollowedView = UIView(frame: view.frame)
hollowedView.backgroundColor = UIColor.clear

//Initialise the layer
let hollowedLayer = CAShapeLayer()

//Draw your two paths and append one to the other
let holePath = UIBezierPath(rect: CGRect(origin: CGPoint(x: (view.frame.width - holeWidth) / 2, y: (view.frame.height - holeWidth) / 2), size: CGSize(width: holeWidth, height: holeWidth)))
let externalPath = UIBezierPath(rect: hollowedView.frame).reversing()
holePath.append(externalPath)
holePath.usesEvenOddFillRule = true

//Assign your path to the path property of your layer
hollowedLayer.path = holePath.cgPath
hollowedLayer.fillColor = UIColor.purple.cgColor
hollowedLayer.opacity = 0.5


//Add your hollowedLayer to the layer of your hollowedView
hollowedView.layer.addSublayer(hollowedLayer)

view.addSubview(hollowedView)

The result looks like this : enter image description here

Upvotes: 2

MBN
MBN

Reputation: 304

Create a custom UIView with background color blue.

class CustomView: UIView {

// Try adding a rect and fill color.

    override func draw(_ rect: CGRect) {

       let ctx = UIGraphicsGetCurrentContext()
       ctx!.beginPath()

       //Choose the size based on the size required.
       ctx?.addRect(CGRect(x: 20, y: 20, width: rect.maxX - 40, height: rect.maxY - 40))

       ctx!.closePath()
       ctx?.setFillColor(UIColor.red.cgColor)
       ctx!.fillPath()

    }
 }

Upvotes: 0

Related Questions