找出窗口中的UIBarButtonItem框架?

UIBarButtonItem不扩展UIView ,所以没有什么像框架属性。

但是,有什么办法可以得到什么是CGRect框架,相对于应用程序UIWindow

你喜欢使用私人API吗? 如是,

 UIView* view = thatItem.view; return [view convertRect:view.bounds toView:nil]; 

定位AppStore当然没有人需要这个。 一个更不可靠的方法,也使用未公开的function,但将通过苹果的testing,是循环通过子视图来查找相应的button项目。

 NSMutableArray* buttons = [[NSMutableArray alloc] init]; for (UIControl* btn in theToolbarOrNavbar.subviews) if ([btn isKindOfClass:[UIControl class]]) [buttons addObject:btn]; UIView* view = [buttons objectAtIndex:index]; [buttons release]; return [view convertRect:view.bounds toView:nil]; 

index删除所有空白项目之后.items数组中的条形项目的索引。 这假定button按照递增的顺序排列,这可能不是。 更可靠的方法是按增加.origin.xsorting buttons数组。 当然这仍然假设酒吧button项目必须inheritanceUIControl类,并且是工具栏/导航栏的直接子视图,也许不是。


正如你所看到的,在处理无证的特征时有很多不确定性。 但是,你只是想在手指下面popup一些东西吗? UIBarButtonItem的.action可以是以下forms的select器:

 -(void)buttonClicked:(UIBarButtonItem*)sender event:(UIEvent*)event; 

注意事件的参数 – 你可以获得触摸的位置

 [[event.allTouches anyObject] locationInView:theWindow] 

或用button查看

 [[event.allTouches anyObject] view] 

因此,不需要迭代子视图或使用未logging的function来执行您想要的操作。

我没有看到这个选项张贴(这在我看来是更简单),所以这里是:

 UIView *barButtonView = [barButtonItem valueForKey:@"view"]; 

在iOS 3.2中,从工具栏button显示一个操作页面popup窗口有一个更简单的方法。 只是做这样的事情:

 - (IBAction)buttonClicked:(UIBarButtonItem *)sender event:(UIEvent *)event { UIActionSheet *popupSheet; // Prepare your action sheet [popupSheet showFromBarButtonItem:sender animated:YES]; } 

这是我用于WEPopover项目的实现:( https://github.com/werner77/WEPopover ):

 @implementation UIBarButtonItem(WEPopover) - (CGRect)frameInView:(UIView *)v { UIView *theView = self.customView; if (!theView.superview && [self respondsToSelector:@selector(view)]) { theView = [self performSelector:@selector(view)]; } UIView *parentView = theView.superview; NSArray *subviews = parentView.subviews; NSUInteger indexOfView = [subviews indexOfObject:theView]; NSUInteger subviewCount = subviews.count; if (subviewCount > 0 && indexOfView != NSNotFound) { UIView *button = [parentView.subviews objectAtIndex:indexOfView]; return [button convertRect:button.bounds toView:v]; } else { return CGRectZero; } } @end 

通过与工具栏一起传递工具条,我可以使Werner Altewischer的WEpopover工作
UIBarButton:Mod在WEPopoverController.m中

 - (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)item toolBar:(UIToolbar *)toolBar permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated { self.currentUIControl = nil; self.currentView = nil; self.currentBarButtonItem = item; self.currentArrowDirections = arrowDirections; self.currentToolBar = toolBar; UIView *v = [self keyView]; UIButton *button = nil; for (UIView *subview in toolBar.subviews) { if ([[subview class].description isEqualToString:@"UIToolbarButton"]) { for (id target in [(UIButton *)subview allTargets]) { if (target == item) { button = (UIButton *)subview; break; } } if (button != nil) break; } } CGRect rect = [button.superview convertRect:button.frame toView:v]; [self presentPopoverFromRect:rect inView:v permittedArrowDirections:arrowDirections animated:animated]; } 

只要UIBarButtonItem (和UITabBarItem )不从UIViewinheritance – 由于历史原因, UIBarIteminheritance自NSObject – 这种疯狂仍在继续(截至本文写作,iOS 8.2和计数…)

在这个线程中最好的答案显然是@ KennyTM的 。 不要傻,使用私有API来查找视图。

这里有一个origin.x Swift解决scheme来获得一个origin.xsorting的数组(就像Kenny的答案所示):

  let buttonFrames = myToolbar.subviews.filter({ $0 is UIControl }).sorted({ $0.frame.origin.x < $1.frame.origin.x }).map({ $0.convertRect($0.bounds, toView:nil) }) 

该数组现在是origin.x使用UIBarButtonItem框架sorting。

(如果您觉得需要阅读更多关于其他人与UIBarButtonItem的斗争,我推荐从2012年的Ash Furrow 的博客文章: 探索UIBarButtonItem )

 -(CGRect) getBarItemRc :(UIBarButtonItem *)item{ UIView *view = [item valueForKey:@"view"]; return [view frame]; } 

你可以从UINavigationBar视图中获取它。 navigationBar是一个UIView,它有2个或3个自定义子栏的部分在栏上。

如果您知道UIBarButtonItem当前显示在右侧的导航栏中,则可以从导航栏的子视图数组中获取其框架。

首先你需要可以从UIViewController的navigationController中获得的navigationBar 。 然后find最右边的子视图:

 UINavigationBar* navbar = curViewController.navigationController.navigationBar; UIView* rightView = nil; for (UIView* v in navbar.subviews) { if (rightView==nil) { rightView = v; } else if (v.frame.origin.x > rightView.frame.origin.x) { rightView = v; // this view is further right } } // at this point rightView contains the right most subview of the navbar 

我没有编译这个代码,所以YMMV。

这不是最好的解决scheme, UIBarBattonItem来看,这不是正确的解决scheme,我们不能这样做,因为我们隐式地访问UIBarBattonItem内的对象,但你可以尝试做如下的事情:

 UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 30, 30)]; [button setImage:[UIImage imageNamed:@"Menu_Icon"] forState:UIControlStateNormal]; [button addTarget:self action:@selector(didPressitem) forControlEvents:UIControlEventTouchUpInside]; UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:button]; self.navigationItem.rightBarButtonItem = item; CGPoint point = [self.view convertPoint:button.center fromView:(UIView *)self.navigationItem.rightBarButtonItem]; //this is like view because we use UIButton like "base" obj for //UIBarButtonItem, but u should note that UIBarButtonItem base class //is NSObject class not UIView class, for hiding warning we implicity //cast UIBarButtonItem created with UIButton to UIView NSLog(@"point %@", NSStringFromCGPoint(point)); 

结果我得到下一个:

点{289,22}

在这里输入图像说明

在实现这个代码之前,一定要在你的Applition委托application:didFinishLaunchingWithOptions:调用[window makeKeyAndVisible] application:didFinishLaunchingWithOptions:方法!

 - (void) someMethod { CGRect rect = [barButtonItem convertRect:barButtonItem.customview.bounds toView:[self keyView]]; } - (UIView *)keyView { UIWindow *w = [[UIApplication sharedApplication] keyWindow]; if (w.subviews.count > 0) { return [w.subviews objectAtIndex:0]; } else { return w; } } 

我处理如下:

 - (IBAction)buttonClicked:(UIBarButtonItem *)sender event:(UIEvent *)event { UIView* view = [sender valueForKey:@"view"]; //use KVO to return the view CGRect rect = [view convertRect:view.bounds toView:self.view]; //do stuff with the rect }