8

How to display only the corners of a UIView?

        let view = UIView()
        view.layer.borderColor = UIColor.white.cgColor

        view.layer.borderWidth = 2 
           let maskframe = UIView(frame: CGRect(x:0, y:0, 
          width:view.frame.width, height:view.frame.height))

         view.layer.mask = maskframe.layer.`

This masks only the right edge and i dont understand how it works either.

like this

Reinier Melian
  • 20,519
  • 3
  • 38
  • 55
Savitha Suresh
  • 321
  • 4
  • 12

4 Answers4

9

Try with this class, here I use a custom view drawing using CoreGraphics, added some Inspectable variables to help with customization

//
//  CornerView.swift
//  CornersViewSO
//
//  Created by Reinier Melian on 5/31/17.
//  Copyright © 2017 Reinier Melian. All rights reserved.
//

import UIKit
import CoreGraphics

@IBDesignable
class CornerView: UIView {

    @IBInspectable
    var sizeMultiplier : CGFloat = 0.2{
        didSet{
            self.draw(self.bounds)
        }
    }

    @IBInspectable
    var lineWidth : CGFloat = 2{
        didSet{
            self.draw(self.bounds)
        }
    }

    @IBInspectable
    var lineColor : UIColor = UIColor.black{
        didSet{
            self.draw(self.bounds)
        }
    }


    override init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = UIColor.clear
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.backgroundColor = UIColor.clear
    }

    func drawCorners()
    {
        let currentContext = UIGraphicsGetCurrentContext()

        currentContext?.setLineWidth(lineWidth)
        currentContext?.setStrokeColor(lineColor.cgColor)

        //first part of top left corner
        currentContext?.beginPath()
        currentContext?.move(to: CGPoint(x: 0, y: 0))
        currentContext?.addLine(to: CGPoint(x: self.bounds.size.width*sizeMultiplier, y: 0))
        currentContext?.strokePath()

        //top rigth corner
        currentContext?.beginPath()
        currentContext?.move(to: CGPoint(x: self.bounds.size.width - self.bounds.size.width*sizeMultiplier, y: 0))
        currentContext?.addLine(to: CGPoint(x: self.bounds.size.width, y: 0))
        currentContext?.addLine(to: CGPoint(x: self.bounds.size.width, y: self.bounds.size.height*sizeMultiplier))
        currentContext?.strokePath()

        //bottom rigth corner
        currentContext?.beginPath()
        currentContext?.move(to: CGPoint(x: self.bounds.size.width, y: self.bounds.size.height - self.bounds.size.height*sizeMultiplier))
        currentContext?.addLine(to: CGPoint(x: self.bounds.size.width, y: self.bounds.size.height))
        currentContext?.addLine(to: CGPoint(x: self.bounds.size.width - self.bounds.size.width*sizeMultiplier, y: self.bounds.size.height))
        currentContext?.strokePath()

        //bottom left corner
        currentContext?.beginPath()
        currentContext?.move(to: CGPoint(x: self.bounds.size.width*sizeMultiplier, y: self.bounds.size.height))
        currentContext?.addLine(to: CGPoint(x: 0, y: self.bounds.size.height))
        currentContext?.addLine(to: CGPoint(x: 0, y: self.bounds.size.height - self.bounds.size.height*sizeMultiplier))
        currentContext?.strokePath()

        //second part of top left corner
        currentContext?.beginPath()
        currentContext?.move(to: CGPoint(x: 0, y: self.bounds.size.height*sizeMultiplier))
        currentContext?.addLine(to: CGPoint(x: 0, y: 0))
        currentContext?.strokePath()
    }


    // Only override draw() if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func draw(_ rect: CGRect) {
        // Drawing code
        super.draw(rect)
        self.drawCorners()
    }


}

EDITED

Example Code of Use

import UIKit

class ViewController: UIViewController {

    var cornerViewCode : CornerView?
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        self.cornerViewCode = CornerView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
        self.view.addSubview(self.cornerViewCode!)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

this is how it looks

enter image description here

Hope this helps

Reinier Melian
  • 20,519
  • 3
  • 38
  • 55
  • thank you. But for me nothing gets displayed.let cv=CornerView() cv.draw(CGRect(x:50,y:(view.frame.height/2-50),width:view.frame.width-100,height:100)) view.addSubview(cv) view.bringSubview(toFront: cv) – Savitha Suresh May 31 '17 at 11:53
  • You need to init with frame, can i share a example code, also you can do this with storyboard or xib – Reinier Melian May 31 '17 at 12:04
  • @SavithaSuresh please check my answer was edited with example code of how use it, best regards – Reinier Melian May 31 '17 at 12:08
  • @SavithaSuresh off the records you never should call .draw method – Reinier Melian May 31 '17 at 12:12
  • thank you. i got it . but without custom class, is there a way to use mask ? – Savitha Suresh May 31 '17 at 12:14
  • ya i got it . but can i do this with mask ? – Savitha Suresh May 31 '17 at 12:24
  • @SavithaSuresh I don't know if you can with mask, I suppose yes, but why you need specifically a mask? my answer works and you can add a view on top of other without problems, can you share all your code to add my class and show you?, Anyway for further SO questions please expose your requirements because your question never explicitly ask for a mask solution – Reinier Melian May 31 '17 at 12:31
  • ya my question doesnot. i just wanted to know about it,because i didnt understand how mask works – Savitha Suresh May 31 '17 at 12:32
  • @SavithaSuresh You can always search in google about it, but SO is not an Tutorials Site is an answers site... – Reinier Melian May 31 '17 at 12:50
  • Please use self.setNeedsDisplay() instead of calling draw. – cvb Jun 29 '18 at 15:32
  • 1
    If you start at (0, height*multiplier) you can eliminate the "second part of top left corner" code section. – Joel Mar 01 '22 at 22:56
1

Check out this UIView:

class RectangleView: UIView {

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

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

    override func draw(_ rect: CGRect) {

        let aPath = UIBezierPath()

        UIColor.black.set()

        aPath.move(to: CGPoint(x: rect.minX, y: 0.1*rect.maxY))
        aPath.addLine(to: CGPoint(x: rect.minX, y: rect.minY))
        aPath.addLine(to: CGPoint(x: 20, y: rect.minY))
        aPath.stroke()

        aPath.move(to: CGPoint(x: rect.maxX - 0.1*rect.maxX, y: rect.minY))
        aPath.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
        aPath.addLine(to: CGPoint(x: rect.maxX, y: 0.1*rect.maxY))
        aPath.stroke()

        aPath.move(to: CGPoint(x: rect.maxX, y: rect.maxY - 0.1*rect.maxY))
        aPath.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
        aPath.addLine(to: CGPoint(x: rect.maxX - 0.1*rect.maxX, y: rect.maxY))
        aPath.stroke()

        aPath.move(to: CGPoint(x: rect.minX + 0.1*rect.maxX, y: rect.maxY))
        aPath.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
        aPath.addLine(to: CGPoint(x: rect.minX, y: rect.maxY - 0.1*rect.maxY))
        aPath.stroke()

    }

}
Kingalione
  • 4,237
  • 6
  • 49
  • 84
0

If you don't wish to subclass UIView. The same can be achieved using Autolayout.

Swift Version: 3.0

Xcode Version 8.2.1

func setupAutoLayout() {
    let cameraViewWidth : Float = Float(UIScreen.main.bounds.size.width * 0.50)

    let edgeLength : Float = cameraViewWidth * 0.10

    cameraView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    cameraView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    cameraView.widthAnchor.constraint(equalToConstant: CGFloat(cameraViewWidth)).isActive = true
    cameraView.heightAnchor.constraint(equalToConstant: CGFloat(cameraViewWidth)).isActive = true

    //Top Left
    topLeftEdgeView.leadingAnchor.constraint(equalTo: cameraView.leadingAnchor).isActive = true
    topLeftEdgeView.topAnchor.constraint(equalTo: cameraView.topAnchor).isActive = true
    topLeftEdgeView.widthAnchor.constraint(equalToConstant: CGFloat(edgeLength)).isActive = true
    topLeftEdgeView.heightAnchor.constraint(equalToConstant: CGFloat(1.0)).isActive = true

    topLeftSideEdgeView.leadingAnchor.constraint(equalTo: cameraView.leadingAnchor).isActive = true
    topLeftSideEdgeView.topAnchor.constraint(equalTo: cameraView.topAnchor).isActive = true
    topLeftSideEdgeView.widthAnchor.constraint(equalToConstant: CGFloat(1.0)).isActive = true
    topLeftSideEdgeView.heightAnchor.constraint(equalToConstant: CGFloat(edgeLength)).isActive = true

    //Top Right
    topRightEdgeView.trailingAnchor.constraint(equalTo: cameraView.trailingAnchor).isActive = true
    topRightEdgeView.topAnchor.constraint(equalTo: cameraView.topAnchor).isActive = true
    topRightEdgeView.widthAnchor.constraint(equalToConstant: CGFloat(edgeLength)).isActive = true
    topRightEdgeView.heightAnchor.constraint(equalToConstant: CGFloat(1.0)).isActive = true

    topRightSideEdgeView.trailingAnchor.constraint(equalTo: cameraView.trailingAnchor).isActive = true
    topRightSideEdgeView.topAnchor.constraint(equalTo: cameraView.topAnchor).isActive = true
    topRightSideEdgeView.widthAnchor.constraint(equalToConstant: CGFloat(1.0)).isActive = true
    topRightSideEdgeView.heightAnchor.constraint(equalToConstant: CGFloat(edgeLength)).isActive = true

    //Bottom Left
    bottomLeftEdgeView.leadingAnchor.constraint(equalTo: cameraView.leadingAnchor).isActive = true
    bottomLeftEdgeView.bottomAnchor.constraint(equalTo: cameraView.bottomAnchor, constant : -CGFloat(1.0)).isActive = true
    bottomLeftEdgeView.widthAnchor.constraint(equalToConstant: CGFloat(edgeLength)).isActive = true
    bottomLeftEdgeView.heightAnchor.constraint(equalToConstant: CGFloat(1.0)).isActive = true

    bottomLeftSideEdgeView.leadingAnchor.constraint(equalTo: cameraView.leadingAnchor).isActive = true
    bottomLeftSideEdgeView.topAnchor.constraint(equalTo: cameraView.bottomAnchor, constant : -CGFloat(edgeLength + 1.0)).isActive = true
    bottomLeftSideEdgeView.widthAnchor.constraint(equalToConstant: CGFloat(1.0)).isActive = true
    bottomLeftSideEdgeView.heightAnchor.constraint(equalToConstant: CGFloat(edgeLength)).isActive = true

    //Bottom Right
    bottomRightEdgeView.trailingAnchor.constraint(equalTo: cameraView.trailingAnchor).isActive = true
    bottomRightEdgeView.bottomAnchor.constraint(equalTo: cameraView.bottomAnchor, constant : -CGFloat(1.0)).isActive = true
    bottomRightEdgeView.widthAnchor.constraint(equalToConstant: CGFloat(edgeLength)).isActive = true
    bottomRightEdgeView.heightAnchor.constraint(equalToConstant: CGFloat(1.0)).isActive = true

    bottomRightSideEdgeView.trailingAnchor.constraint(equalTo: cameraView.trailingAnchor).isActive = true
    bottomRightSideEdgeView.topAnchor.constraint(equalTo: cameraView.bottomAnchor, constant : -CGFloat(edgeLength + 1.0)).isActive = true
    bottomRightSideEdgeView.widthAnchor.constraint(equalToConstant: CGFloat(1.0)).isActive = true
    bottomRightSideEdgeView.heightAnchor.constraint(equalToConstant: CGFloat(edgeLength)).isActive = true
}

enter image description here

PS: Where cameraView, topLeftEdgeView, topLeftSideEdgeView... etc all are UIViews.

Here our edgeLength is dependent on cameraView width(currently 10%). At 0.50 this will draw complete border around cameraView.

Don't Forget to add translatesAutoresizingMaskIntoConstraints = false for all views involved!!

iOSer
  • 2,241
  • 1
  • 18
  • 26
0

I was able to achieve the same via BeizerPath and CAShapeLayer. Hence sharing the same.

Code created on Xcode 9.3 using Swift 4.0. Tested on iOS 10.0 and iOS 11.3

  func createCorners() -> Void {

        //Calculate the length of corner to be shown
        let cornerLengthToShow = self.bounds.size.height * 0.10
        print(cornerLengthToShow)

        // Create Paths Using BeizerPath for all four corners
        let topLeftCorner = UIBezierPath()
        topLeftCorner.move(to: CGPoint(x: self.bounds.minX, y: self.bounds.minY + cornerLengthToShow))
        topLeftCorner.addLine(to: CGPoint(x: self.bounds.minX, y: self.bounds.minY))
        topLeftCorner.addLine(to: CGPoint(x: self.bounds.minX + cornerLengthToShow, y: self.bounds.minY))

        let topRightCorner = UIBezierPath()
        topRightCorner.move(to: CGPoint(x: self.bounds.maxX - cornerLengthToShow, y: self.bounds.minY))
        topRightCorner.addLine(to: CGPoint(x: self.bounds.maxX, y: self.bounds.minY))
        topRightCorner.addLine(to: CGPoint(x: self.bounds.maxX, y: self.bounds.minY + cornerLengthToShow))

        let bottomRightCorner = UIBezierPath()
        bottomRightCorner.move(to: CGPoint(x: self.bounds.maxX, y: self.bounds.maxY - cornerLengthToShow))
        bottomRightCorner.addLine(to: CGPoint(x: self.bounds.maxX, y: self.bounds.maxY))
        bottomRightCorner.addLine(to: CGPoint(x: self.bounds.maxX - cornerLengthToShow, y: self.bounds.maxY ))

        let bottomLeftCorner = UIBezierPath()
        bottomLeftCorner.move(to: CGPoint(x: self.bounds.minX, y: self.bounds.maxY - cornerLengthToShow))
        bottomLeftCorner.addLine(to: CGPoint(x: self.bounds.minX, y: self.bounds.maxY))
        bottomLeftCorner.addLine(to: CGPoint(x: self.bounds.minX + cornerLengthToShow, y: self.bounds.maxY))

        let combinedPath = CGMutablePath()
        combinedPath.addPath(topLeftCorner.cgPath)
        combinedPath.addPath(topRightCorner.cgPath)
        combinedPath.addPath(bottomRightCorner.cgPath)
        combinedPath.addPath(bottomLeftCorner.cgPath)

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = combinedPath
        shapeLayer.strokeColor = UIColor.blue.cgColor
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.lineWidth = 3

        layer.addSublayer(shapeLayer)
    }
iOSer
  • 2,241
  • 1
  • 18
  • 26