UINavigationBar Touch
Я хотел бы вызвать событие при касании, когда пользователь удаляет заголовок панели навигации одного из моих представлений.
Я немного пораньше, могу ли я получить доступ к виду заголовка UINavigationBar, чтобы подключить к нему событие касания.
Возможно ли это?
Ответы
Ответ 1
Решение, которое я нашел, - это кнопка, я использую следующее (но я не знаю, как это "законно" ):
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");
}
который запустил "Контракт заголовка" на консоли!
То, как я это делал, может быть совершенно неверным, но может дать вам представление о том, что вы можете посмотреть. Это, конечно, помогло мне! Вероятно, есть лучший способ сделать это.
Ответ 2
Вы можете добавить распознаватель жестов, чтобы быть одним нажатием на заголовок навигационного контроллера.
Я обнаружил, что в subviews 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
Таким образом, вы можете использовать это для одного нажатия, или вы можете реализовать любой распознаватель жестов, который вы хотите в этом названии.
Ответ 3
Ни один из других ответов не помог мне. Вместо того, чтобы добавлять жест к существующему подъярусу навигационной панели или заменять 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];
}
Ответ 4
Ссылка на класс UINavigationItem
имеет свойство titleView
, которое вы можете установить в свой пользовательский UIView
.
Другими словами, создайте подкласс UIView
с помощью ваших обработчиков касаний, а затем, когда вы нажмете свой элемент навигации, установите для этого элемента свойство titleView
экземпляр вашего подкласса.
Ответ 5
Это самое простое и простое решение в Swift, просто скопируйте/вставьте и заполните пробелы:
let navTapGesture = UITapGestureRecognizer(target: <#T##AnyObject?#>, action: <#T##Selector#>)
navigationItem.titleView.userInteractionEnabled = true
navigationItem.titleView.addGestureRecognizer(navTapGesture)
Обязательно установите userInteractionEnabled
на true
на titleView
, по умолчанию отключен.
Ответ 6
Я не хотел указывать кнопку как пользовательский 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!
Ответ 7
Один из возможных вариантов: (Использовать 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;
Ответ 8
Это можно сделать, связав UITapGestureRecognizer
с надзором навигационной панели, соответствующим заголовку title.
Поскольку индекс 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")
}
}