UIBarButtonItem
does not extend UIView
, so there is nothing like a frame property.
But is there any way I can get what is it\'s CGRec
Before implement this code, be sure to call [window makeKeyAndVisible]
in your Applition delegate application:didFinishLaunchingWithOptions:
method!
- (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;
}
}
This is not the best solution and from some point of view it's not right solution and we can't do like follow because we access to object inside UIBarBattonItem
implicitly, but you can try to do something like:
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));
as result i got next:
point {289, 22}
I handled it as follows:
- (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
}
This is the implementation I use for my WEPopover project: (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
As long as UIBarButtonItem
(and UITabBarItem
) does not inherit from UIView
—for historical reasons UIBarItem
inherits from NSObject
—this craziness continues (as of this writing, iOS 8.2 and counting ... )
The best answer in this thread is obviously @KennyTM's. Don't be silly and use the private API to find the view.
Here's a oneline Swift solution to get an origin.x
sorted array (like Kenny's answer suggests):
let buttonFrames = myToolbar.subviews.filter({
$0 is UIControl
}).sorted({
$0.frame.origin.x < $1.frame.origin.x
}).map({
$0.convertRect($0.bounds, toView:nil)
})
The array is now origin.x
sorted with the UIBarButtonItem
frames.
(If you feel the need to read more about other people's struggles with UIBarButtonItem, I recommend Ash Furrow's blog post from 2012: Exploring UIBarButtonItem)