2014-10-09 92 views
22

有人可以帮助我认识一个水龙头当用户点击标题导航栏认识点击导航栏标题

我想识别这个水龙头,然后动画tableHeaderView出现。可能滑动TableView。

想法是,用户可以选择一个快速选项(从tableViewHeader)重新填充TableView。

但是我无法识别任何水龙头。

我正在使用Swift。

谢谢。

回答

38

UINavigationBar不公开其内部层次结构。没有支持的方式来获得显示标题的UILabel的引用。

您可以通过“手动”(通过搜索其subviews)在其视图层次结构中扎根,但由于视图层次结构是私有的,因此可能会在未来的iOS版本中停止工作。

一种解决方法是创建一个UILabel并将其设置为您的视图控制器的navigationItem.titleView。您可以根据默认标签的样式进行匹配,这可能会在不同版本的iOS中更改。

这就是说,它是很容易设置:

override func didMove(toParentViewController parent: UIViewController?) { 
    super.didMove(toParentViewController: parent) 

    if parent != nil && self.navigationItem.titleView == nil { 
     initNavigationItemTitleView() 
    } 
} 

private func initNavigationItemTitleView() { 
    let titleView = UILabel() 
    titleView.text = "Hello World" 
    titleView.font = UIFont(name: "HelveticaNeue-Medium", size: 17) 
    let width = titleView.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)).width 
    titleView.frame = CGRect(origin:CGPoint.zero, size:CGSize(width: width, height: 500)) 
    self.navigationItem.titleView = titleView 

    let recognizer = UITapGestureRecognizer(target: self, action: #selector(YourViewController.titleWasTapped)) 
    titleView.userInteractionEnabled = true 
    titleView.addGestureRecognizer(recognizer) 
} 

@objc private func titleWasTapped() { 
    NSLog("Hello, titleWasTapped!") 
} 

我(使用sizeThatFits:)标签的大小设置为它的自然宽度,但我高度设置为500。导航栏将保持宽度,但将高度缩小到酒吧自己的高度。这样可以最大限度地挖掘可用区域(因为标签的自然高度可能只有〜22点,但酒吧的点高为44点)。

+0

完美的解决方案。 我完全同意不通过视图层次结构进行搜索,就像我发现的其他示例一样,因为将来可能无法使用。 非常感谢。 – Richard 2014-10-10 06:04:02

+2

我自己几乎在那里,但没有怀疑'userInteractionEnabled'。 +1。 – 2016-09-28 08:59:40

+0

我有这个解决方案的问题。在稍后更新uilabel中的文本时,由于某种原因,标签本身跳转到x 0(屏幕最左侧)。看起来像UIKit中的错误。反正周围? (iOS 10.1.1) – Jonny 2016-11-04 02:28:00

15

这是一个解决方案,尽管不是超级优雅。在故事板中,只需在标题上放置一个常规的UIButton并将其附加到ViewController中的IBAction。您可能需要为每个视图执行此操作。

+2

这是很好的解决方案,实际上,可以完美运行,易于实现。 – Evgenii 2015-06-29 23:58:28

4

有一个更简单,更优雅的使用手势识别器的解决方案(至少在iOS 9及以上版本中)。

UITapGestureRecognizer * titleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(titleTapped)]; 
[self.navigationItem.titleView addGestureRecognizer:titleTapRecognizer]; 

然后添加标题挖掘方法:

-(void) titleTapped { 
    // Called when title is tapped 
} 
+3

不要忘记像接受的答案中那样定义'self.navigationItem.titleView'。缺省值为零。 – Jonny 2016-11-04 02:37:20

1

一个简单的方法可能只是产生点击手势识别器并将其连接到您的导航栏元素。

// on viewDidLoad 
let tapGestureRecognizer = UITapGestureRecognizer(target:self, action: #selector(YourViewController.somethingWasTapped(_:))) 
self.navigationController?.navigationBar.addGestureRecognizer(tapGestureRecognizer) 

func somethingWasTapped(_ sth: AnyObject){ 
    print("Hey there") 
} 
+1

最好的方法来做到这一点。 – 2017-02-10 15:02:36

+3

在我的情况下,在另一个viewcontroller被推入堆栈之后,这打破了后退按钮的功能。 – Georg 2017-03-10 15:59:46

+3

它会打破导航栏中其他按钮的功能 – 2017-05-18 14:20:32

3

布鲁诺的回答对我来说是90%。但我注意到的一件事是,一旦将此手势识别器添加到其中,则导航控制器的UIBarButtonItem功能在其他视图控制器中停止工作。为了解决这个问题,我只是删除从导航控制器手势当视图正准备消失:

var tapGestureRecognizer : UITapGestureRecognizer! 

override func viewWillAppear(_ animated: Bool) { 

    tapGestureRecognizer = UITapGestureRecognizer(target:self, action: #selector(self.navBarTapped(_:))) 

    self.navigationController?.navigationBar.addGestureRecognizer(tapGestureRecognizer) 

} 

override func viewWillDisappear(_ animated: Bool) { 

    self.navigationController?.navigationBar.removeGestureRecognizer(tapGestureRecognizer) 

} 

func navBarTapped(_ theObject: AnyObject){ 

    print("Hey there") 

}