Долгое нажатие на кнопку возврата UINavigationItem
Я хочу добавить функциональность к своим кнопкам назад через мое приложение на основе UINavigationController, где долгое нажатие кнопки "Назад" появится в корне. Однако я не могу понять, где можно прикрепить распознаватель жестов. Я подклассифицирую UINavigationBar и пытаюсь определить, находится ли длинное нажатие в области левой кнопки?
Я слышал о том, что раньше люди добавляли подобные функции. У кого-нибудь есть идеи?
Ответы
Ответ 1
Я считаю, что UIGestureRecognizers можно добавлять только в UIViews и подклассы UIViews.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIView_Class/UIView/UIView.html
Задняя кнопка - это UIBarButtonItem, который спускается из NSObject. Таким образом, вы не сможете подключить распознаватель жестов к стандартной кнопке "Назад", используя
UILongPressGestureRecognizer *longPressGesture =
[[[UILongPressGestureRecognizer alloc]
initWithTarget:self action:@selector(longPress:)] autorelease];
[self.navigationItem.backBarButtonItem addGestureRecognizer:longPressGesture];
Однако вы можете добавить пользовательский вид в UIBarButtonItem. Пользовательский вид также мог бы быть UIView, UIButton, UILabel и т.д.
Пример:
UIView *myTransparentGestureView = [[UIView alloc] initWithFrame:CGRectMake(0,0,40,30)];
[myTransparentGestureView addGestureRecognizer:longPressGesture];
[self.navigationItem.backBarButtonItem setCustomView:myTransparentGestureView];
// Or you could set it like this
// self.navigationItem.backBarButtonItem.customView = myTransparentGestureView;
[myTransparentGestureView release];
Однако вы должны быть осторожны, поскольку настройка свойств на backBarButtonItem применима к следующему виду, которое вы нажимаете. Поэтому, если у вас есть вид A, который подталкивает к просмотру B, и вы хотите, чтобы жест был распознан, когда вы возвращаетесь в поле зрения B. Вы должны настроить его на вид A.
Ответ 2
Я знаю, что этот вопрос старый, но я придумал решение. Вместо того, чтобы пытаться добавить распознаватель жестов к самой кнопке (которая была бы идеальной), я добавил ее в self.navigationController.navigationBar
, а затем в методе действий, используя locationInView
, чтобы увидеть, переполнен ли я на кнопку "Назад". Я не был полностью уверен в том, как точно идентифицировать кнопку "назад", поэтому я неуклюже просто хватаю первый подкласс с координатой x меньше некоторой произвольной величины, но кажется многообещающим. Если у кого-то есть лучший способ определить рамку кнопки "Назад", сообщите мне.
- (void)longPress:(UILongPressGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateEnded)
{
// set a default rectangle in case we don't find the back button for some reason
CGRect rect = CGRectMake(0, 0, 100, 40);
// iterate through the subviews looking for something that looks like it might be the right location to be the back button
for (UIView *subview in self.navigationController.navigationBar.subviews)
{
if (subview.frame.origin.x < 30)
{
rect = subview.frame;
break;
}
}
// ok, let get the point of the long press
CGPoint longPressPoint = [sender locationInView:self.navigationController.navigationBar];
// if the long press point in the rectangle then do whatever
if (CGRectContainsPoint(rect, longPressPoint))
[self doWhatever];
}
}
- (void)addLongPressGesture
{
if (NSClassFromString(@"UILongPressGestureRecognizer"))
{
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
[self.navigationController.navigationBar addGestureRecognizer:longPress];
[longPress release];
}
}
Ответ 3
Я пошел немного по-другому, подумал, что я поделюсь им. Вышеуказанные ответы прекрасны, но на самом деле, если длинное нажатие находится в ведущей 1/3 панели навигации, это достаточно хорошо для меня:
- (void)longPress:(UILongPressGestureRecognizer *)gr
{
NSLog(@"longPress:");
UINavigationBar *navBar = [self navigationBar];
CGFloat height = navBar.bounds.size.height;
CGPoint pt = [gr locationOfTouch:0 inView:navBar];
//NSLog(@"PT=%@ height=%f", NSStringFromCGPoint(pt), height);
if(CGRectContainsPoint(CGRectMake(0,0,100,height), pt)) {
[self popToViewController:self.viewControllers[0] animated:YES];
}
}
Ответ 4
Здесь мое решение:
В appDelegate ( "владелец" панели навигации в моем приложении), In applicationDidFinishLaunchingWithOptions:
Получить представление навигационной панели и добавить распознаватель жестов на весь вид:
// Get the nav bar view
UINavigationBar *myNavBar = nil;
for (UIView *view in [self.window.rootViewController.view subviews]) {
if ([view isKindOfClass:[UINavigationBar class]]) {
NSLog(@"Found Nav Bar!!!");
myNavBar = (UINavigationBar *)view;
}
}
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self
action:@selector(backButtonLongPress:)];
[myNavBar addGestureRecognizer:longPress];
NSLog(@"Gesture Recognizer Added.");
Затем в appDelegate, in - (void) backButtonLongPress: (id) отправитель
Проверьте, не происходит ли жест в кадре обратной кнопки:
if ([sender state] == UIGestureRecognizerStateBegan) {
// Get the nav bar view
UINavigationBar *myNavBar = nil;
for (UIView *view in [self.window.rootViewController.view subviews]) {
if ([view isKindOfClass:[UINavigationBar class]]) {
NSLog(@"Found Nav Bar!!!");
myNavBar = (UINavigationBar *)view;
}
}
// Get the back button view
UIView *backButtonView = nil;
for (UIView *view in [myNavBar subviews]) {
if ([[[view class] description] isEqualToString:@"UINavigationItemButtonView"]) {
backButtonView = view;
NSLog(@"Found It: %@", backButtonView);
NSLog(@"Back Button View Frame: %f, %f; %f, %f", backButtonView.frame.origin.x, backButtonView.frame.origin.y, backButtonView.frame.size.width, backButtonView.frame.size.height);
}
}
CGPoint longPressPoint = [sender locationInView:myNavBar];
NSLog(@"Touch is in back button: %@", CGRectContainsPoint(backButtonView.frame, longPressPoint) ? @"YES" : @"NO");
if (CGRectContainsPoint(backButtonView.frame, longPressPoint)) {
// Place your action here
}
// Do nothing if outside the back button frame
}