UINavigationBar Touch

问题描述 投票:21回答:9

当用户点击我的一个视图的导航栏标题时,我想触摸一个事件。

我是否可以访问UINavigationBar标题的视图,以便将触摸事件连接到它,我有点不知所措。

这甚至可能吗?

ios iphone cocoa-touch uikit uinavigationbar
9个回答
30
投票

我找到的解决方案是一个按钮,我使用以下(但我不知道它是如何“合法”):

UIButton *titleLabelButton = [UIButton buttonWithType:UIButtonTypeCustom];
[titleLabelButton setTitle:@"myTitle" forState:UIControlStateNormal];
titleLabelButton.frame = CGRectMake(0, 0, 70, 44);
titleLabelButton.font = [UIFont boldSystemFontOfSize:16];
[titleLabelButton addTarget:self action:@selector(didTapTitleView:) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.titleView = titleLabelButton;

把那些代码放在你设置标题的地方。然后我在其他地方测试:

- (IBAction)didTapTitleView:(id) sender
{
    NSLog(@"Title tap");
}

在控制台上记录了“标题点击”!

我这样做的方式可能完全错误,但可能会让你知道你可以看到什么。这肯定帮助了我!尽管如此,可能还有更好的方法。


43
投票

您可以添加手势识别器,只需点击一下导航控制器的标题即可。我发现在navigationBar子视图中,标题是索引1的标题,左键的索引是0,右键的索引是2。

UITapGestureRecognizer *navSingleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(navSingleTap)];
navSingleTap.numberOfTapsRequired = 1;
[[self.navigationController.navigationBar.subviews objectAtIndex:1] setUserInteractionEnabled:YES];
[[self.navigationController.navigationBar.subviews objectAtIndex:1] addGestureRecognizer:navSingleTap];

然后在您的实现中的某处实现以下内容。

-(void)navSingleTap

因此,您可以将其用于单击,或者您可以在该标题上实现您想要的任何手势识别器。


25
投票

其他答案都不适合我。而不是将一个手势添加到navigationBar的现有子视图,或者替换titleView,我只是添加了一个清晰的UIView,覆盖了导航栏的很大一部分......

- (void) setupNavbarGestureRecognizer {
    // recognise taps on navigation bar to hide
    UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showHideNavbar)];
    gestureRecognizer.numberOfTapsRequired = 1;
    // create a view which covers most of the tap bar to
    // manage the gestures - if we use the navigation bar
    // it interferes with the nav buttons
    CGRect frame = CGRectMake(self.view.frame.size.width/4, 0, self.view.frame.size.width/2, 44);
    UIView *navBarTapView = [[UIView alloc] initWithFrame:frame];
    [self.navigationController.navigationBar addSubview:navBarTapView];
    navBarTapView.backgroundColor = [UIColor clearColor];
    [navBarTapView setUserInteractionEnabled:YES];
    [navBarTapView addGestureRecognizer:gestureRecognizer];
}

9
投票

UINavigationItem类引用具有titleView属性,您可以将其设置为自定义UIView

换句话说,使用触摸处理程序创建UIView的子类,然后在推送导航项时,将该项的titleView属性设置为子类的实例。


3
投票

这是Swift中最简单,最简单的解决方案,只需复制/粘贴并填写空白:

let navTapGesture = UITapGestureRecognizer(target: <#T##AnyObject?#>, action: <#T##Selector#>)
navigationItem.titleView.userInteractionEnabled = true
navigationItem.titleView.addGestureRecognizer(navTapGesture)

一定要在userInteractionEnabled上将true设置为titleView,默认为关闭。


1
投票

我不想将按钮指定为自定义titleView,因为这意味着我不能再使用标准标题了。另一方面,在向导航栏添加点击手势识别器时,我们必须确保在点击栏按钮时不会触发。

这个解决方案完成了两个(添加到UINavigationBar子类):

- (void)awakeFromNib {
    // put in -initWithFrame: if initialized manually
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(ft_titleTapped:)];
    [self addGestureRecognizer:tap];
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    UIView *titleView = [self valueForKey:@"titleView"];
    CGRect titleFrame = titleView.frame;
    titleFrame.origin.y = 0; // expand to full height of navBar
    titleFrame.size.height = self.frame.size.height;
    return CGRectContainsPoint(titleFrame, [gestureRecognizer locationInView:self]);
}

- (void)ft_titleTapped:(UITapGestureRecognizer*)sender {
    if (sender.state == UIGestureRecognizerStateEnded) {
        // could add some checks here that the delegate is indeed a navigation controller
        UIViewController<FTViewControllerAdditions> *viewController = (id)[((UINavigationController*)self.delegate) topViewController];
        if ([viewController respondsToSelector:@selector(titleViewTapped:)]) {
            [viewController titleViewTapped:self];
        }
    }
}

它会自动向视图控制器发送-titleViewTapped:消息(如果已实现)。在UITableViewController子类中,您可以实现这样的方法以滚动到顶部功能:

- (void)titleViewTapped:(id)sender {
    [self.tableView setContentOffset:CGPointMake(0, -self.tableView.contentInset.top) animated:YES];
}

警告:我们正在使用未记录的-valueForKey:@"titleView"检索标题视图。从技术上讲,它不使用私有API,但在未来的iOS版本中可能仍会失败!


1
投票

其中一个可能的选择:(使用UILabel)

UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doSomething:)];
UILabel * titleView = [UILabel new];
titleView.text = @"Test";
[titleView sizeToFit];
titleView.userInteractionEnabled = YES;
[titleView addGestureRecognizer:tapGesture];

self.navigationItem.titleView = titleView;

1
投票

这可以通过将UITapGestureRecognizer附加到与titleView对应的导航栏子视图来完成。

由于titleView的索引取决于有多少条形按钮项目,因此需要遍历所有导航栏子视图以查找正确的视图。

import UIKit

class ViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()

    addTitleViewTapAction("tapped", numberOfTapsRequired: 3)
  }

  func addTitleViewTapAction(action: Selector, numberOfTapsRequired: Int) {

    if let subviews = self.navigationController?.navigationBar.subviews {
      for subview in subviews {
        // the label title is a subview of UINavigationItemView
        if let _ = subview.subviews.first as? UILabel {
          let gesture = UITapGestureRecognizer(target: self, action: action)
          gesture.numberOfTapsRequired = numberOfTapsRequired
          subview.userInteractionEnabled = true
          subview.addGestureRecognizer(gesture)
          break
        }
      }
    }
  }

  @objc func tapped() {

    print("secret tap")
  }
}

0
投票

this answerthis one的基础上,我采用了下面的“功能”方法,我不确定它是否更具可读性,但我更喜欢它突破循环。

    if let navTitle = self.navigationController?.navigationBar.subviews.first(where: {$0.subviews.first is UILabel}) {
        let gesture = UITapGestureRecognizer(target: self, action: action)
        gesture.numberOfTapsRequired = numberOfTapsRequired
        navTitle.isUserInteractionEnabled = true
        navTitle.addGestureRecognizer(gesture)
    }
© www.soinside.com 2019 - 2024. All rights reserved.