我希望通过基于UINavigationController的应用程序为我的后退按钮添加功能,其中长按后退按钮将弹出到root。但是,我无法弄清楚手势识别器的附加位置。我是否将UINavigationBar子类化并尝试检测长按是否在左按钮区域?
我之前听说有人添加类似的功能。有人有什么想法吗?
答案 0 :(得分:18)
我知道这个问题已经过时了,但我想出了一个解决方案。我没有尝试将手势识别器添加到按钮本身(这是理想的),而是将其添加到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's 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];
}
}
答案 1 :(得分:6)
我相信UIGestureRecognizers只能添加到UIViews和UIViews的子类中。
后退按钮是一个来自NSObject的UIBarButtonItem。因此,您将无法使用
将手势识别器附加到标准后退按钮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 :(得分: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];
}
}
答案 3 :(得分:1)
这是我的解决方案:
在appDelegate(我的应用中导航栏的&#34;所有者&#34;)中,在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中,在 - (void)backButtonLongPress:(id)sender
检查手势是否出现在后退按钮的框架内:
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
}