Bezier Paths & Shape Layers in Swift 3.0

“Flairs of your personality are reflected by the crafts you carve within!!
Similarly the output of your App is reflected by the designs you design within”

Necessity

It is not today that the graphics have emerged in IT  industry, but there continuous presence has really raised the bars for developers to keep on emerging with the graphics trendsetters.Well, to grow your graphic standards we need to grab its roots first. Lets start like a beginner & return like a pro.

Basics

First things first. The only time we are struck in app is not much in constraints or app design but the point when you have to actually make changes within your UIView components. So lets jump on to them one by one:

  1. UIBezierPath: You can use this class to create vector-based paths. This class is a wrapper for the path-related features in the Core Graphics framework. You can use this class to define simple shapes, such as ovals and rectangles, as well as complex shapes that incorporate multiple straight and curved line segments. This class provides many initializers to draw the paths as per your requirements.
  2. draw(_ rect: CGRect):  A bezier path that is created by the above class cannot stand on its own. It needs a Core Graphics context where it can be rendered to. Use  UIView‘s draw(_:) method provided by default. The context needed is provided automatically then.
  3. CAShapeLayer & Masks: The draw(_: ) method in an UIView subclass provides a context for the bezier path that will be drawn. However, it’s not always necessary to override that method to perform custom drawing, and actually, you should avoid it if possible, as it has impact to the performance. A good alternative is using CAShapeLayer objects, which are rendered much faster and you have additional flexibility by using them.
    A CAShapeLayer is a CALayer subclass, and by creating and using such objects we actually add extra layers to a view. It has several properties that can be set for customising the final outcome of a view, and most of them are animatable, meaning that their values can be changed using animated manners.
    When creating a CAShapeLayer object, it’s necessary to specify its shape, or in other words its path. The most easy way to set that path is by creating a bezier path first, and then assigning it to the shape layer object. Then this shape layer is added to the UIView layer or mask.Now, mask comes into picture.
    Actually a CAShapeLayer object can be added to the UIView by 2 ways :
    myView.layer.addSublayer(sublayaerObj)  or myView.layer.mask = sublayerObj
  4. Sub Layer V/S Mask: Let us understand the difference between adding a shape layer as sub layer or adding it as a mask on UIView.
    For instance, if you make a triangular bezier path in your shape layer and then initialize the CAShapeLayer object with the

     

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = myBezierPath.cgPath
        myView.layer.addSublayer(shapeLayer)

    This is the case when you have added shape layer as a layer to the view. So, the entire part of the view will be captured by  this layer & the path we added will be displayed on this layer.
    But when the shape layer is added as mask in following way:

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = myBezierPath.cgPath
        myView.layer.mask = shapeLayer

    In this case, any part of the view that is not a part of the path is clipped, and the view actually takes the shape of the shape layer that is applied as a mask.

Dive like a Pro

Well now all the candy points of core graphics have been touched well enough. So, there are many situations where we have to manipulate the actual view components to match the app designs. Let’s deal with one such point – for an instance,If we need to round the corners of view, we will just do it with following line:

myView.layer.cornerRadius = 15.0

But what if we need to round the 2 opposite corners of a view. This is something to relate with view customization. It may seem tedious at 1 point but following above terms, it can be easily achieved.

Let’s follow these simple steps to achieve some rounded corners:

  1. Make CustomView class subclassing UIView class.

  2. Define its instance parameter of UIBezierPath class

  3. Override the draw(_ rect: CGRect) method & initialize bezierPath in it.

  4. Finally set the class of your view to  CustomView.

class CustomView : UIView {

 var path:UIBezierPath!

 override func draw(_ rect: CGRect) {

     path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: [.topLeft,.bottomRight], cornerRadii: CGSize(width: 15.0, height: 0.0))

     UIColor.orange.setFill()
     path.fill()
     UIColor.purple.setStroke()
     path.stroke()
   }
}

Note: Instead of using draw(_:) method, you can also add the path to view with shape layer.

This is the output :

Corner view

That is all for this lesson.Keep cool Keep coding!!!

Leave a Reply