Reputation: 3850
The following is a image for which the the code does not align the centre of the UIView , white color.
CAShapeLayer *layer = [CAShapeLayer layer];
layer.anchorPoint=CGPointMake(0.5, 0.5);
layer.path=[UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 75.0, 75.0)].CGPath;
layer.fillColor =[UIColor redColor].CGColor;
[self.shapeView.layer addSublayer:layer];
Upvotes: 7
Views: 8179
Reputation: 320
I've encounter same case like this. The final resolution is shapeLayer.needsDisplayOnBoundsChange = true
and update CAShapeLayer frame in layoutSubviews
, CenteredAlignShapeView can adjust when using Auto Layout.
class CenteredAlignShapeView: UIView {
public let dot = CAShapeLayer()
init() {
super.init(frame: .zero)
dot.needsDisplayOnBoundsChange = true
layer.insertSublayer(dot, at: 0)
dot.fillColor = UIColor.red.cgColor
}
override func layoutSubviews() {
super.layoutSubviews()
dot.frame = bounds
let circlePath = UIBezierPath(arcCenter: CGPoint(x: bounds.width/2, y: bounds.height/2), radius: 4, startAngle: 0, endAngle: CGFloat.pi*2, clockwise: true)
dot.path = circlePath.cgPath
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Upvotes: 0
Reputation: 688
For those still have issue with centering this approach worked for me:
1- Set the shape layer frame equal to parent view frame.
shapeLayer.frame = view.frame
2- remove the shape layer position property.
// shapeLayer.position = CGPoint(x: ,y: )
3- set x and y value of your bezier path equal to zero.
UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: self.width, height:
self.height))
Only these should be enough, get rid of the rest.
======
If that didn't work, then try this one:
@IBDesignable class YourView: UIView {
private var shapeLayer: CAShapeLayer!
override func draw(_ rect: CGRect) {
self.shapeLayer = CAShapeLayer()
self.shapeLayer.path = bezierPath.cgPath
self.shapeLayer.fillColor = UIColor.blue.cgColor
let bezierPathHeight = self.bezierPath.cgPath.boundingBox.height
let bezierPathWidth = self.bezierPath.cgPath.boundingBox.width
self.shapeLayer.setAffineTransform(CGAffineTransform.init(translationX: self.bounds.width / bezierPathWidth, y: self.bounds.height / bezierPathHeight))
self.shapeLayer.setAffineTransform(CGAffineTransform.init(scaleX: self.bounds.width / bezierPathHeight, y: self.bounds.height / bezierPathHeight))
self.layer.addSublayer(self.shapeLayer)
}
Upvotes: 0
Reputation: 4708
anchorPoint
is not for setting the position of CAShapeLayer, use position
instead.
let layer = CAShapeLayer()
layer.borderColor = UIColor.blackColor().CGColor
layer.borderWidth = 100
layer.bounds = CGRectMake(0, 0, 50, 50)
layer.position = myView.center
layer.fillColor = UIColor.redColor().CGColor
view.layer.addSublayer(layer)
Edit
Sorry for such a rough answer before, the code above may not work as you want, here is the correct answer I just come out. A important thing to note is: How you draw the oval path did effect the position of your CAShapeLayer
let layer = CAShapeLayer()
myView.layer.addSublayer(layer)
layer.fillColor = UIColor.redColor().CGColor
layer.anchorPoint = CGPointMake(0.5, 0.5)
layer.position = CGPointMake(myView.layer.bounds.midX, myView.layer.bounds.midY)
layer.path = UIBezierPath(ovalInRect: CGRectMake(-75.0 / 2, -75.0 / 2, 75.0, 75.0)).CGPath
From Apple Document,
The oval path is created in a clockwise direction (relative to the default coordinate system)
In other word, the oval path is drawn from the edge instead of the center, so you must take into accound the radius of the oval you are drawing. In your case, you need to do this:
layer.path = UIBezierPath(ovalInRect: CGRectMake(-75.0 / 2, -75.0 / 2, 75.0, 75.0)).CGPath
Now we ensure that the center of drawn path is equal to the center of CAShapeLayer
. Then we can use position
property to move the CAShapeLayer
as we want. The image below could help you understand.
Upvotes: 22
Reputation: 3244
CAShapeLayer *layer = [CAShapeLayer layer];
layer.anchorPoint=CGPointMake(0.5, 0.5);
layer.path=[UIBezierPath bezierPathWithOvalInRect:CGRectMake((self.shapeView.frame.size.width/2)-37.5, (self.shapeView.frame.size.height/2)-37.5, 75.0, 75.0)].CGPath;
//37.5 means width & height divided by 2
layer.fillColor =[UIColor redColor].CGColor;
[self.shapeView.layer addSublayer:layer];
Upvotes: 0