Will Ullrich
Will Ullrich

Reputation: 2238

Obtain Bezier Path of CALayer

CALayer objects have a property accessibilityPath which as stated is supposedly

Returns the path of the element in screen coordinates.

Of course as expected this does not return the path of the layer.

Is there a way to access the physical path of a given CALayer that has already been created? For instance, how would you grab the path of a UIButton's layer property once the button has been initialized?

EDIT

For reference, I am trying to detect whether a rotated button contains a point. The reason for the difficulty here is due to the fact that the buttons are drawn in a curved view...

My initial approach was to create bezier slices then pass them as a property to the button to check if the path contains the point. For whatever reason, there seems to be an ugly offset from the path and the button.

They are both added to the same view and use the same coordinates / values to determine their frame, but the registered path seems to be offset to the left from the actual drawn shape from the path. Below is an image of the shapes I have drawn. The green outline is where the path is drawn (and displayed....) where the red is approximately the area which registers as inside the path...

enter image description here

I'm having a hard time understanding how the registered area is different.

If anyone has any ideas on why this offset would be occurring would be most appreciated.

UPDATE

Here is a snippet of me adding the shapes. self in this case is simply a UIView added to a controller. it's frame is the full size of the controller which is `{0, height_of_device - controllerHeight, width_of_device, controllerHeight}

UIBezierPath *slicePath = UIBezierPath.new;

[slicePath moveToPoint:self.archedCenterRef];
[slicePath addArcWithCenter:self.archedCenterRef radius:outerShapeDiameter/2 startAngle:shapeStartAngle endAngle:shapeEndAngle clockwise:clockwise];
[slicePath addArcWithCenter:self.archedCenterRef radius:(outerShapeDiameter/2 - self.rowHeight) startAngle:shapeEndAngle endAngle:shapeStartAngle clockwise:!clockwise];
[slicePath closePath];

CAShapeLayer *sliceShape = CAShapeLayer.new;
sliceShape.path = slicePath.CGPath;
sliceShape.fillColor = [UIColor colorWithWhite:0 alpha:.4].CGColor;
[self.layer addSublayer:sliceShape];

...
...

button.hitTestPath = slicePath;

In a separate method in my button subclass to detect if it contains the point or not: (self here is the button of course)

...
if ([self.hitTestPath containsPoint:touchPosition]) {
    if (key.alpha > 0 && !key.isHidden) return YES;
    else return NO;
}
else return NO;

Upvotes: 0

Views: 1730

Answers (1)

user2782993
user2782993

Reputation: 193

You completely missunderstood the property, this is for assistive technology, from the docs:

Excerpt:

"The default value of this property is nil. If no path is set, the accessibility frame rectangle is used to highlight the element.

When you specify a value for this property, the assistive technology uses the path object you specify (in addition to the accessibility frame, and not in place of it) to highlight the element."

You can only get the path from a CAShapeLayer, alls other CALayers don't need to be drawn with a path at all.

Update to your update:

I think the offset is due to a missing

UIView convert(_ point: CGPoint, to view: UIView?)

The point needs to be converted to the buttons coordinate systems.

Upvotes: 2

Related Questions