Objective c 检测长时间按压UINavigationItem';s后退按钮
我想通过基于UINavigationController的应用程序为我的后退按钮添加功能,长按后退按钮将弹出到root。但是,我不知道在哪里安装手势识别器。我是否要将UINavigationBar子类化,并尝试检测长按是否位于左按钮区域Objective c 检测长时间按压UINavigationItem';s后退按钮,objective-c,ios,uinavigationcontroller,uinavigationbar,uigesturerecognizer,Objective C,Ios,Uinavigationcontroller,Uinavigationbar,Uigesturerecognizer,我想通过基于UINavigationController的应用程序为我的后退按钮添加功能,长按后退按钮将弹出到root。但是,我不知道在哪里安装手势识别器。我是否要将UINavigationBar子类化,并尝试检测长按是否位于左按钮区域 我以前听说有人添加了类似的功能。有人有什么想法吗?我相信UIGestureRecognitors只能添加到UIView和UIView的子类中 “后退”按钮是从NSObject派生的UIBarButtonim。因此,您将无法使用将手势识别器附加到标准后退按钮 U
我以前听说有人添加了类似的功能。有人有什么想法吗?我相信UIGestureRecognitors只能添加到UIView和UIView的子类中 “后退”按钮是从NSObject派生的UIBarButtonim。因此,您将无法使用将手势识别器附加到标准后退按钮
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];
但是,您必须小心,因为在BackBarButtonim上设置属性适用于您推送的下一个视图。因此,如果您的视图A推动视图B,并且您希望在视图B中回击时能够识别该手势。您必须在视图A中进行设置。我知道这个问题很老,但我想出了一个解决方案。我没有尝试将手势识别器添加到按钮本身(这很理想),而是将其添加到
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];
}
}
-(void)longPress:(uilongpress gesture识别器*)发送方
{
if(sender.state==UIGestureRecognitizerStateEnded)
{
//设置一个默认矩形,以防由于某种原因找不到“后退”按钮
CGRect rect=CGRectMake(0,0,100,40);
//在子视图中迭代,查找看起来可能是返回按钮的正确位置的内容
用于(self.navigationController.navigationBar.subview中的UIView*子视图)
{
if(子视图.frame.origin.x<30)
{
rect=子视图.frame;
打破
}
}
//好吧,让我们来谈谈长篇大论的要点
CGPoint longPressPoint=[发送方位置查看:self.navigationController.navigationBar];
//如果长按点位于矩形中,则执行任何操作
if(CGRectContainsPoint(rect,longPressPoint))
[自我陶醉];
}
}
-(无效)添加长按手势
{
if(NSClassFromString(@“UILongPressGestureRecognitor”))
{
UILongPressGestureRecognizer*longPress=[[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)];
[self.navigationController.navigationBar AddgestureRecognitor:longPress];
[新闻稿];;
}
}
我走了一条稍有不同的道路,我想我会分享它。上面的答案很好,但实际上,如果长按位于导航条的前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];
}
}
以下是我的解决方案:
在appDelegate(我的应用程序中导航栏的“所有者”)中,在ApplicationIDFinishLaunchingWithOptions中:
获取导航栏视图,并将手势识别器添加到整个视图中:
// 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
}
向backButtomItem上的自定义视图添加手势识别器对我不起作用。。。识别器拒绝开火。您是否能够使用上面的代码使其工作?它可能不工作,因为BackbarButtonim是只读的,因此不接受自定义视图。您很可能需要创建自己的LeftBarbuttonite,如下面的答案所示。啊,但我失去了我的背箭,除非我找到一个图像。。。可能不值得。不过还是要谢谢你!好主意。下次我需要这样做的时候,我会试试你的方法。谢谢你的跟进!只要长按一下就可以弹出,这对我来说是合理的。我有相同的要求,比如在后退按钮上设置长按手势。这种方法的问题是后退按钮不会保持高亮显示状态。因此我将cancelsTouchesInView属性设置为否。但是,我的长按处理程序和backButton处理程序都会显示呼叫。有什么解决方案吗???@user1010819不,没有什么能让我感到惊讶。不过,老实说,如果我今天要解决这个问题,毫无疑问我不会使用这个技巧将长按手势添加到标准导航控制器中(因为最终用户在标准导航栏等标准UI控件上使用自定义行为很容易混淆)。我会用我自己的看起来不同的图形按钮来替换后退按钮(让用户知道在这个应用程序中工作的方式不同),可能会用我自己的自定义容器类来替换整个导航控制器和导航栏。我也做了同样的事情。但使用自定义后退按钮会弄乱交互式弹出手势。在浪费了2-3天之后,我无法找到合适的工作解决方案,因此我继续进行,并找到了解决方法问题的方法。为了防止BackbarButtonim操作处理程序执行,我在中将cancelsTouchesInView设置为YESUILongPressGestureRecognitizerStateEnded。此操作有效。