I'm trying to setup a new feature walkthrough for my users, and as part of that I'd like to draw a circle around a relevant UI element. I'm trying to draw a circle around a UIBarButtonItem in the upper right of the NavigationBar, but when I translate the frame coordinates to the main window, something in the math isn't right and the red circle is offset too far to the right.
In the screenshot, I'm trying to draw a red circle around the second button (the one the popover is pointing at), but when I translate the coordinates, it actually draws around the 3rd button. When I run the same code on the first button (the search magnifying glass) it works just fine and the red circle is drawn correctly.
In my code, I'm just grabbing the barButtonItem
from the popover, and I've verified it points to the correct button.
if let buttonItem = self.popoverPresentationController?.barButtonItem {
if let view = buttonItem.value(forKey: "view") as? UIView,
let mainView = containingViewController?.navigationController?.view {
let viewFrame = view.frame
print("viewFrame: \(viewFrame)")
// This should be translating coords to the main window.
let windowRect = view.convert(viewFrame, to: nil)
print("Window RECT \(windowRect)")
let circlePath = UIBezierPath(ovalIn: windowRect)
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.cgPath
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.lineWidth = 3.0
mainView.layer.addSublayer(shapeLayer)
}
}
I print out the view
's frame, and those numbers seem correct, but the translated windowRect
is off when it's not the left most button in the navbar.
For the search button (the left most one in the screenshot):
viewFrame: (0.0, 0.0, 46.0, 44.0)
Window RECT (617.0, 27.0, 46.0, 44.0)
For the second button (the one pointed to by the popover in the screenshot), Window RECT is offset by 108 instead of 54 as expected:
viewFrame: (54.0, 0.0, 46.0, 44.0)
Window RECT: (725.0, 27.0, 46.0, 44.0)
Each UIBarButtonItem is 46 wide, and I assume spacing in between of 8. That gives the starting x of 54.0 in the second set of numbers. But when translated to the Window coordinates, somehow that becomes a difference of 108; so it's offset by a whole button. I've tried to target the 3rd and 4th buttons, and it's always off by one full button width. As you can see the red circle is centered on the 3rd button, but that's not the one I'm trying to highlight.
I've tried to translate to mainView
instead of to: nil
when doing view.convert
, but it doesn't make any difference. The numbers come back exactly the same. Any thoughts on what I'm doing wrong, or is this a but (known or otherwise) and I'm going to have to do crazy things in my code to make it work right?
Updated to add: If I remove the translation, and just put the layer in the superview of the view I found:
let circlePath = UIBezierPath(ovalIn: viewFrame)
// code to create shapelayer
view.superview?.layer.addSublayer(highlightItemLayer!)
Then it's displaying in the correct location. I'd like it to be higher in the view hierarchy so I can draw it on top of other things; so still want to be able to do the translation if possible.