I want to get position(point) of my navigation item which is a button. If I can get this point I will be able to add a guide circle on my app. But I can't get this point right.
let point = searchBarButton.center
or
let point = view.convert(CGPoint(x: searchBarButton.center.x, y: searchBarButton.center.y + UIApplication.shared.statusBarFrame.height), from: view)
y
point was calculated correctly when I added the status bar height. But x
point always has the value as 20
and it doesn't make sense. So how do I get the x
point correctly?
Here's my code and a screenshot of my app.
class ViewController: UIViewController {
let searchBarButton = UIButton()
// MARK: - viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
configureNavigationBarItems()
let added_view: UIView = navigationController?.view ?? view
let point = added_view.convert(CGPoint(x: searchBarButton.center.x, y: searchBarButton.center.y + UIApplication.shared.statusBarFrame.height), from: added_view)
addCircle(point: point)
}
func configureNavigationBarItems() {
searchBarButton.setImage(UIImage(named: "icon_search_border"), for: .normal)
searchBarButton.frame = CGRect.init(x: 0, y: 0, width: 40, height: 40)
let searchBarButtonItem = UIBarButtonItem.init(customView: searchBarButton)
self.navigationItem.setRightBarButton(searchBarButtonItem, animated: true)
}
func addCircle(point: CGPoint) {
let overlayView = UIView(frame: self.view.bounds)
overlayView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
self.navigationController?.view.addSubview(overlayView)
let circlePath = UIBezierPath(arcCenter: point,
radius: 30,
startAngle: 0.0,
endAngle: 2.0 * .pi,
clockwise: true)
let path = CGMutablePath()
path.addPath(circlePath.cgPath)
path.addRect(overlayView.frame)
let maskLayer = CAShapeLayer()
maskLayer.path = path
maskLayer.fillRule = .evenOdd
overlayView.layer.mask = maskLayer
overlayView.layer.masksToBounds = true
}
}
When you want to access to nav bar items you should access them in viewDidAppear and thats the answer of my question. It's inspired from @jawadAli's answer.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if let navigationBarSubviews = self.navigationController?.navigationBar.subviews {
for view in navigationBarSubviews {
if let findClass = NSClassFromString("_UINavigationBarContentView"),
view.isKind(of: findClass),
let barButtonView = self.navigationItem.rightBarButtonItem?.value(forKey: "view") as? UIView {
let point = barButtonView.convert(barButtonView.center, to: view)
addCircle(point: CGPoint(x: point.x, y: point.y + UIApplication.shared.statusBarFrame.height))
}
}
}
}