如何获取导航栏(NavBar)中标题的X和Y坐标?
解决导航栏标题坐标获取的问题
这个问题我之前也踩过坑,核心问题在于你混淆了bounds和frame的区别,而且如果时机不对,titleView可能还没完成布局,自然拿不到正确的值~
下面分两种常见场景给你解决方案:
场景1:你自定义了titleView(通过Storyboard或代码设置的自定义视图)
首先要等视图布局完成后再获取坐标,推荐在viewDidLayoutSubviews方法里操作——这个方法会在视图所有子控件布局完成后调用,此时titleView的frame才是准确的:
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() // 获取标题视图相对于导航栏的坐标 if let titleView = navigationItem.titleView { let navBarRelativeOrigin = titleView.frame.origin print("标题相对于导航栏的X:\(navBarRelativeOrigin.x),Y:\(navBarRelativeOrigin.y)") // 如果需要相对于屏幕的坐标,用坐标系转换方法 let screenRelativeOrigin = titleView.convert(titleView.bounds.origin, to: nil) print("标题相对于屏幕的X:\(screenRelativeOrigin.x),Y:\(screenRelativeOrigin.y)") } }
场景2:使用系统默认的导航栏标题(未自定义titleView)
这种情况下navigationItem.titleView是nil,你需要遍历导航栏的子视图找到内置的标题Label:
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() // 遍历导航栏子视图,筛选出标题Label if let titleLabel = navigationController?.navigationBar.subviews.first(where: { $0 is UILabel }) as? UILabel { let navBarRelativeOrigin = titleLabel.frame.origin print("默认标题相对于导航栏的X:\(navBarRelativeOrigin.x),Y:\(navBarRelativeOrigin.y)") // 转换为屏幕坐标系的坐标 let screenRelativeOrigin = titleLabel.convert(titleLabel.bounds.origin, to: nil) print("默认标题相对于屏幕的X:\(screenRelativeOrigin.x),Y:\(screenRelativeOrigin.y)") } }
关键提示
- 绝对不要在
viewDidLoad里直接获取坐标!此时视图还没完成布局,titleView的frame还未确定,大概率返回nil或错误值; bounds是视图自身的坐标系,原点默认是(0,0),所以用它拿坐标完全不对,要获取相对于父视图或屏幕的位置,必须用frame或者坐标系转换方法。
内容的提问来源于stack exchange,提问作者Olek
相关产品推荐
相关产品推荐

