How to set the contentGravity variable of CALayer to 'resizeAspectFill'?

1.1k Views Asked by At

I am trying to set the contentGravity variable of a CALayer but I am not quite sure how to do this. I have tried the following without success:

var layer = CAShapeLayer.init()
layer.contentGravity = .resizeAspectFill // This is not recognised

My UIImageView presents the image taken from the camera of the phone. I then use the Vision Framework to detect rectangles, which return the four corner coordinates of the detected rectangle. I then draw the rectangle in the layer of the UIImageView. The content mode of the UIIMageView is 'Aspect Fill'. My rectangle is currently misaligned and i think it has to do with the contentGravity of the layer. Please see image below:

Rectangle drawn into CAShapelayer:

let rec = UIBezierPath.init()
    rec.move(to: CGPoint.init(x: topLeft.x, y: topLeft.y))
    rec.addLine(to: CGPoint.init(x: topRight.x, y: topRight.y))
    rec.addLine(to: CGPoint.init(x: bottomRight.x, y: bottomRight.y))
    rec.addLine(to: CGPoint.init(x: bottomLeft.x, y: bottomLeft.y))
    rec.close()

    self.layer.opacity = 0.4
    self.layer.path = rec.cgPath
    self.layer.lineWidth = 5
    self.layer.strokeColor = UIColor.yellow.cgColor
    self.layer.frame = self.imgPreViewOutlet.bounds

    self.imgPreViewOutlet.layer.addSublayer(self.layer)

image show misaligned rectangle drawn in the layer of UIImageView

1

There are 1 best solutions below

2
matt On

There is no purpose in setting the content gravity of a CAShapeLayer, as it will in no way affect how the shape is drawn. Content gravity is meaningful only for a layer with content, e.g. a CGImage that is drawn into its contents property.

Here's an example where contentsGravity matters; same image, same layer size, different content gravity:

enter image description here

override func viewDidLoad() {
    super.viewDidLoad()
    do {
        let layer = CALayer()
        layer.frame = CGRect(x: 100, y: 100, width: 250, height: 200)
        layer.contents = UIImage(named:"smiley")!.cgImage
        layer.borderWidth = 1
        self.view.layer.addSublayer(layer)
        layer.contentsGravity = .center
    }
    do {
        let layer = CALayer()
        layer.frame = CGRect(x: 100, y: 300, width: 250, height: 200)
        layer.contents = UIImage(named:"smiley")!.cgImage
        layer.borderWidth = 1
        self.view.layer.addSublayer(layer)
        layer.contentsGravity = .resize
    }
}

But if we try exactly the same thing with a shape layer, the content gravity makes no difference:

enter image description here

override func viewDidLoad() {
    super.viewDidLoad()
    do {
        let layer = CAShapeLayer()
        layer.frame = CGRect(x: 100, y: 100, width: 250, height: 200)
        layer.path = CGPath(rect: CGRect(x: 0, y: 0, width: 20, height: 20), transform: nil)
        layer.borderWidth = 1
        self.view.layer.addSublayer(layer)
        layer.contentsGravity = .center
    }
    do {
        let layer = CAShapeLayer()
        layer.frame = CGRect(x: 100, y: 300, width: 250, height: 200)
        layer.path = CGPath(rect: CGRect(x: 0, y: 0, width: 20, height: 20), transform: nil)
        layer.borderWidth = 1
        self.view.layer.addSublayer(layer)
        layer.contentsGravity = .resize
    }
}