In short:
frame
or bounds
for a CAShapeLayer
automatically (and Apple HAS NOT implemented an equivalent of [UIView sizeThatFits]
)So, what's the correct way to programmatically set the frame of a newly-created CAShapeLayer
with a newly-added CGPath
? Apple's docs are silent on the matter.
Things I've tried, that don't work:
CAShapeLayer
CGPath
, add it to the layerframe
- it's {{0,0},{0,0}}
layer.frame = CGPathGetBoundingBox( layer.path )
Frame is now correct, but the path is now DOUBLE offset - changing the frame
causes the path to effectively be shifted an extra (x,y)
pixels
Set: layer.bounds = CGPathGetBoundingBox( layer.path )
layer.position = CGPathGetBoundingBox( layer.path ).origin
One thing I've tried that DID work, but causes problems elsewhere:
EDIT: this BREAKS as soon as you auto-rotate the screen. My guess: Apple's auto-rotate requires control of the "transform" property.
CAShapeLayer
CGPath
, add it to the layer{{0,0},{0,0}}
layer.frame = CGPathGetBoundingBox( layer.path )
layer.transform = CGAffineTransformMakeTranslation( CGPathGetBoundingBox( layer.path ).origin.x * -1, // same for y-coord: set it to "-1 * the path's origin
This works, but ... lots of 3rd party code assumes that the initial transform for a CALayer
is Identity.
It shouldn't be this difficult! Surely there's something I'm doing wrong here?
(I've had one suggestion: "every time you add a path, manually run a custom function to shift all the points by -1 * (top-left-point.x, top-left-point.y)
". Again, that works - but it's ridiculously complex)
Setting layer.bounds to the path bounds is the right thing to do — you want to make the layer's local coordinate space match the path. But you then also need to set the layer's position property to move it into the right place in its superlayer.
(Setting .frame translates into the framework computing the right values of .bounds and .position for you, but it always leaves bounds.origin untouched, which is not what you want when your path bounds has a non-zero origin.)
So something like this should work, assuming you haven't changed the anchorPoint from its usual (.5, .5) value and want to position the layer flush to the origin of its superlayer:
CGRect r = CGPathGetBoundingBox(layer.path);
layer.bounds = r;
layer.position = CGPointMake(r.size.width*.5, r.size.height*.5);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With