ios UINavigationBar 触摸

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2077025/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:47:31  来源:igfitidea点击:

UINavigationBar Touch

iosiphonecocoa-touchuikituinavigationbar

提问by mootymoots

I would like to fire an event on touch when a user taps the title of the navigation bar of one of my views.

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

I'm at a bit of a loss on whether I can access the view of the title of the UINavigationBar in order to wire up a touch event to it.

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

Is this even possible?

这甚至可能吗?

回答by phmagic

You can add a gesture recognizer to be a single tap to the title of the navigation controller. I found that in the navigationBar subviews, the title is the one at index 1, the left button's index is 0 and the right button's index is 2.

您可以将手势识别器添加到导航控制器的标题上。我发现在导航栏子视图中,标题是索引 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];

and then implement the following somewhere in your implementation.

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

-(void)navSingleTap

So you can use this for a single tap, or you can implement any gesture recognizer you want on that title.

因此,您只需轻按一下即可使用它,或者您可以在该标题上实现您想要的任何手势识别器。

回答by phmagic

The solution I found is a button, I use the following (but I don't know how "legal" it is):

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

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;

Put that bit of code where ever you set your title. Then elsewhere I had this to test:

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

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

which logged "Title tap" on the console!

在控制台上记录了“Title tap”!

The way I've gone about this may be completely wrong, but might give you an idea on what you can look in to. It's certainly helped me out! There's probably a better way of doing it though.

我处理此问题的方式可能完全错误,但可能会让您了解可以查看的内容。它当然帮助了我!不过,可能有更好的方法。

回答by Rik Smith-Unna

None of the other answers worked well for me. Rather than add a gesture to an existing subview of the navigationBar, or replace the titleView, I simply added a clear UIView covering a good portion of the 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];
}

回答by Alex Reynolds

The UINavigationItemclass reference has a titleViewproperty, which you can set to your custom UIView.

UINavigationItem类引用有一个titleView属性,它可以设置为自定义UIView

In other words, make a subclass of UIViewwith your touch handlers, and then when you push your navigation item, set that item's titleViewproperty to an instance of your subclass.

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

回答by Beau Nouvelle

This is the simplest and easiest solution in Swift, just copy/paste and fill in the blanks:

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

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

Be sure to set the userInteractionEnabledto trueon the titleView, its off by default.

确保将 设置userInteractionEnabledtrueon titleView,默认情况下为 off。

回答by Ortwin Gentz

I didn't want to specify a button as a custom titleViewbecause that would mean I can't use the standard title anymore. On the other hand, when adding a tap gesture recognizer to the navigation bar, we have to make sure that it doesn't fire when tapping a bar button.

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

This solution accomplishes both (to be added to a UINavigationBarsubclass):

此解决方案实现了两者(要添加到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];
        }
    }
}

It automatically sends a -titleViewTapped:message to the view controller (if implemented). In a UITableViewControllersubclass you could implement the method like this for a scroll to top feature:

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

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

Caution: we're retrieving the title view using the undocumented -valueForKey:@"titleView". It's technically not using a private API but might still fail in a future iOS version!

注意:我们正在使用未记录的-valueForKey:@"titleView". 它在技术上没有使用私有 API,但在未来的 iOS 版本中可能仍然会失败!

回答by JapCon

One of the possible options: (Use UILabel)

可能的选项之一:(使用 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;

回答by bizz84

This can be done by attaching a UITapGestureRecognizerto the navigation bar subview that corresponds to the titleView.

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

As the titleView's index varies depending on how many bar button items there are, it is necessary to iterate through all the navigation bar subviews to find the correct view.

由于 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")
  }
}

回答by Gavin

Building on this answerand this one, I went with the below "functional" approach, I am not sure it is anymore readable, but I prefer it over breaking out of a loop.

建设这个答案这一个,我用下面的“功能性”的方式去了,我不知道它是更易读,但我更喜欢它在一个循环的爆发。

    if let navTitle = self.navigationController?.navigationBar.subviews.first(where: {##代码##.subviews.first is UILabel}) {
        let gesture = UITapGestureRecognizer(target: self, action: action)
        gesture.numberOfTapsRequired = numberOfTapsRequired
        navTitle.isUserInteractionEnabled = true
        navTitle.addGestureRecognizer(gesture)
    }