识别点击导航栏标题

2020/12/16 07:11 · ios ·  · 0评论

可能有人请帮助我认识一个水龙头时,在用户点击标题导航栏

我想识别此点击,然后为出现tableHeaderView设置动画可能将TableView向下滑动。

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

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

我正在使用Swift。

谢谢。

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点)。

从答案中,我们可以看出有两种方法可以做到这一点。

  1. a添加UITapGestureRecognizertitleView这看起来并不优雅,并且需要您手动设置导航栏标题字体,所以我不建议您这样做。
  2. a添加UITapGestureRecognizernavigationBar这看起来很优雅,但是采用这种方法的已发布答案的问题在于,它们都会导致导航栏中的控件无法正常工作。这是我对这种方法的实现,可以使您的控件继续工作。

// Declare gesture recognizer
var tapGestureRecognizer: UITapGestureRecognizer!

override func viewDidLoad() {

    // Instantiate gesture recognizer
    tapGestureRecognizer = UITapGestureRecognizer(target:self, action: #selector(self.navigationBarTapped(_:)))
}

override func viewWillAppear(_ animated: Bool) {

    // Add gesture recognizer to the navigation bar when the view is about to appear
    self.navigationController?.navigationBar.addGestureRecognizer(tapGestureRecognizer)

    // This allows controlls in the navigation bar to continue receiving touches
    tapGestureRecognizer.cancelsTouchesInView = false
}

override func viewWillDisappear(_ animated: Bool) {

    // Remove gesture recognizer from navigation bar when view is about to disappear
    self.navigationController?.navigationBar.removeGestureRecognizer(tapGestureRecognizer)
}

// Action called when navigation bar is tapped anywhere
@objc func navigationBarTapped(_ sender: UITapGestureRecognizer){

    // Make sure that a button is not tapped.
    let location = sender.location(in: self.navigationController?.navigationBar)
    let hitView = self.navigationController?.navigationBar.hitTest(location, with: nil)

    guard !(hitView is UIControl) else { return }

    // Here, we know that the user wanted to tap the navigation bar and not a control inside it 
    print("Navigation bar tapped")

}

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

布鲁诺的答案对我来说是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")

}

一种简单的方法可能就是创建点击手势识别器并将其附加到导航栏元素。

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

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

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

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

然后添加标题点击方法:

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

至于navigationItem.titleViewUIView实在的,我结束了使用UIButton这给所有的灵活性外的框。

override func viewDidLoad() {

    // Create title button
    let titleViewButton = UIButton(type: .system)
    titleViewButton.setTitleColor(UIColor.black, for: .normal)
    titleViewButton.setTitle("Tap Me", for: .normal)

    // Create action listener
    titleViewButton.addTarget(self, action: #selector(YourViewController.titleViewButtonDidTap), for: .touchUpInside)

    // Set the title view with newly created button
    navigationItem.titleView = titleViewButton
}

@objc func titleViewButtonDidTap(_ sender: Any) {
    print("Title did tap")
}

Zia:您的guard !(hitView is UIControl)解决方案在iOS 9下运行时对我来说效果很好,但是当我在更新的iOS版本中运行相同的代码时,当禁用轻按的barButton时,它无法将hitView作为UIControl看到。

我的导航栏中有许多UIBarButtonItems。启用这些barButton时,我的UITapGestureRecognizer操作中的(hitView为UIControl)正确运行,并且该操作功能退出。但是,如果禁用了UIBarButtonItem且用户点击了按钮,则其(hitView is UIControl)为false,并且代码将继续进行,就像用户点击了导航栏一样。

我发现要解决此问题的唯一方法是使用以下方法为viewWillAppear中的所有barButton获取UIView对象:

button1View = button1Item.value(forKey: "view") as? UIView

等等...

然后在我的UITapGestureRecognizer动作函数中测试:

if [button1View, button2View, button3View, button4View].contains(hitView)
{
  return
}

这是一个丑陋的解决方法!知道为什么(hitView是UIControl)在禁用的条形按钮上应该返回false吗?

本文地址:http://ios.askforanswer.com/shibiedianjidaohanglanbiaoti.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!