web-dev-qa-db-ja.com

UINavigationBarタッチ

ユーザーが自分のビューの1つのナビゲーションバーのタイトルをタップしたときに、タッチでイベントを発生させたいのですが。

タッチイベントを接続するためにUINavigationBarのタイトルのビューにアクセスできるかどうかについて少し戸惑っています。

これも可能ですか?

21
mootymoots

私が見つけた解決策はボタンです、私は以下を使用します(しかしそれがどれほど「合法」であるかはわかりません):

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");
}

コンソールに「タイトルタップ」を記録しました!

私がこれについて行った方法は完全に間違っているかもしれませんが、あなたが何を調べることができるかについてあなたにアイデアを与えるかもしれません。それは確かに私を助けてくれました!しかし、おそらくそれを行うためのより良い方法があります。

30
user262490

ジェスチャレコグナイザを追加して、ナビゲーションコントローラのタイトルをシングルタップすることができます。 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

したがって、これをシングルタップに使用することも、そのタイトルに任意のジェスチャ認識機能を実装することもできます。

43
phmagic

他の答えはどれも私にとってうまくいきませんでした。ナビゲーションバーの既存のサブビューにジェスチャを追加したり、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];
}
25
Rik Smith-Unna

UINavigationItemクラス参照には titleView プロパティがあり、カスタムUIViewに設定できます。

つまり、タッチハンドラーを使用してUIViewのサブクラスを作成し、ナビゲーションアイテムをプッシュするときに、そのアイテムのtitleViewプロパティをサブクラスのインスタンスに設定します。

9
Alex Reynolds

これはSwiftで最も簡単で簡単なソリューションであり、コピー/貼り付けして空白を埋めるだけです。

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

userInteractionEnabledtruetitleViewに設定してください。デフォルトではオフになっています。

3
Beau Nouvelle

可能なオプションの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
JapCon

これは、titleViewに対応するナビゲーションバーのサブビューにUITapGestureRecognizerをアタッチすることで実行できます。

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")
  }
}
1
bizz84

ボタンをカスタム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:メッセージをViewControllerに自動的に送信します(実装されている場合)。 UITableViewControllerサブクラスでは、トップへのスクロール機能に対して次のようなメソッドを実装できます。

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

注意:文書化されていない-valueForKey:@"titleView"を使用してタイトルビューを取得しています。技術的にはプライベートAPIを使用していませんが、将来のiOSバージョンでは失敗する可能性があります!

1
Ortwin Gentz

この回答これ に基づいて、以下の「機能的な」アプローチを採用しました。もう読みやすいかどうかはわかりませんが、ループ。

    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)
    }
0
Gavin