2010-06-08 24 views

回答

125

你喜歡用private API嗎?如果是的話,

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

當然針對AppStore的時候沒有人願意這樣。 A 更不可靠方法,也使用未公開的功能,但將通過蘋果的測試,是循環通過子視圖來查找相應的按鈕項。

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數組中刪除所有空白的項目後。這假設按鈕排列順序增加,這可能不是。更可靠的方法是排序buttons數組中增加.origin.x值。當然,這仍然假設酒吧按鈕項目必須繼承UIControl類,並且是工具欄/導航欄的直接子視圖,它可能不是。


正如您所看到的,處理無證件功能時存在很多不確定因素。但是,你只是想在手指右下方彈出一些東西?該的UIBarButtonItem的.action的形式可以是一個選擇:

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

注意事件參數 - 你可以獲取觸摸的位置

[[event.allTouches anyObject] locationInView:theWindow] 

[[event.allTouches anyObject] view] 
的按鈕來查看

因此,不需要迭代子視圖或使用未記錄的功能來執行您想要的操作。

+5

我忘記有關該事件的參數。這顯然是最好的選擇。 – progrmr 2010-06-14 16:09:52

+1

事件參數ftw。非常感謝。 – 2010-07-29 04:49:15

+0

不錯的。謝謝! – Kalle 2011-03-30 11:18:51

1

您可以從UINavigationBar視圖中獲取它。 navigationBar是一個UIView,其中有2個或3個自定義subviews用於欄上的零件。

如果您知道UIBarButtonItem當前顯示在右側的導航欄中,則可以從導航欄的子視圖數組中獲取其框架。

首先您需要navigationBar,您可以從navigationController中獲得這些信息,您可以從UIViewController中獲取該信息。然後找到最右邊的子視圖:

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。

8

在iOS 3.2中,通過工具欄按鈕顯示一個操作頁面彈出窗口有一個更簡單的方法。僅僅做這樣的事情:

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

這隻適用於iPad。 – 2013-05-26 20:56:34

4

這是我用我的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 
+1

不幸的是,這至少有時不起作用。我有一個以編程方式創建的UIBarButtonItems,我發現當customView設置爲非零然後爲零時,欄按鈕項消失,[parentView.subviews objectAtIndex:indexOfView]崩潰(indexOfView不小於subviews.count)。 – 18446744073709551615 2011-12-27 10:29:21

+0

這不適用於我 – Bogdan 2012-07-16 08:45:01

+0

我使用當前(和工作)實現編輯答案 – 2013-05-24 11:46:36

2

我能得到沃納Altewischer的WEpopover通過傳遞了工具欄的工作隨着
UIBarButton: 國防部在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]; 
} 
-1

在實施此代碼之前,請務必在您的Applition代理application:didFinishLaunchingWithOptions:方法中撥打[window makeKeyAndVisible]

- (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; 
} 
} 
+0

「UIBarButtonItem」實例沒有「bounds」屬性。 – 2013-05-17 17:34:21

+0

代碼不訪問barButtonItem的邊界。它正在訪問barButtonItem中的自定義視圖的邊界。 – 2015-12-03 16:52:15

16

我沒有看到這個選項發佈(這在我看來是簡單得多),所以在這裏它是:

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

這不是一個好的解決方案,因爲它使用Apple私有API。 – 2014-11-19 19:06:16

+0

valueForKey:是唯一使用的方法。它不是一個私人API。這裏所做的全部工作就是假設蘋果不保證蘋果的執行情況。 – Gerard 2015-10-23 16:20:23

+0

@Gerard「view」是這裏的私有API。 – bugloaf 2016-01-14 15:55:58

-1

我處理它,如下所示:

- (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 
} 
+0

使用私有API,因此它不是一個好的解決方案。 – 2014-11-19 20:39:13

+0

「-valueForKey:是一種文檔化的公共方法,KVC API提供了一種防止直接實例變量訪問的方法,因此如果該值是可訪問的,那麼不會採取任何措施禁止訪問,一個問題可能是未定義的值在iOS的未來版本中,爲了解決這個問題,你可以將調用封裝在一個try-block中,並且即使你覺得你不能在應用程序商店中使用它,這並不意味着有人針對越獄的設備在其應用中無法使用這種方法。「用戶@ jeremy-w-sherman在另一篇文章中寫道 – 2014-11-26 03:18:23

2

只要UIBarButtonItem(和UITabBarItem)不會從UIView繼承 - 由於歷史原因UIBarItem繼承自NSObject - 這種瘋狂仍在繼續(因此寫作,iOS 8.2和計數...)

在這個線程中最好的答案顯然是@KennyTM's。不要傻,並使用私有API來查找視圖。

這裏的一個ONELINE夫特溶液得到一個origin.x排序後的數組(如Kenny's answer建議):

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.xUIBarButtonItem幀排序。

(如果你覺得需要了解更多關於其他人的使用的UIBarButtonItem鬥爭,我建議Ash Furrow's博客帖子從2012年:Exploring UIBarButtonItem

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

這是不是最好的解決方案,從某些角度來看它不正確的解決方案,我們不能做這樣的後續,因爲我們訪問內部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}

enter image description here

+0

使用tap操作中的event參數仍然是抓取tap時發生的最安全的方法。但如果你需要找出沒有檢測到水龍頭框架,我會說這是一個很好的解決方案**如果**你檢查rightBarButtonItem爲respondsToSelector。 – leolobato 2016-03-11 09:53:40

+0

謝謝,好點 – gbk 2016-03-11 11:38:40