UIBarButtonItem
,其中包含UIButton
。
UIButton
上有一个addTarget:action:
。在该操作中,我呈现一个弹出窗口。我目前是从sender.frame
(即UIButton
的框架)进行呈现,我想改为从UIBarButtonItem
进行呈现。如何从
UIButton
访问UIBarButtonItem
?UIBarButtonItem
,其中包含UIButton
。
UIButton
上有一个addTarget:action:
。在该操作中,我呈现一个弹出窗口。我目前是从sender.frame
(即UIButton
的框架)进行呈现,我想改为从UIBarButtonItem
进行呈现。UIButton
访问UIBarButtonItem
?UIButton
设置为UIBarButtonItem
的customView
,或者将其作为自定义视图的子视图,则可以从按钮开始向上遍历视图层次结构,直到找到包含该按钮的UIToolbar
或UINavigationBar
,然后在该栏的项目中搜索其自定义视图是该按钮(或该按钮的祖先)的项目。
以下是我完全未经测试的代码。 您可以调用[[self class] barButtonItemForView:myButton]
来获取包含您的按钮的项。
+ (BOOL)ifBarButtonItem:(UIBarButtonItem *)item containsView:(UIView *)view storeItem:(UIBarButtonItem **)outItem {
UIView *customView = item.customView;
if (customView && [view isDescendantOfView:customView]) {
*outItem = item;
return YES;
} else {
return NO;
}
}
+ (BOOL)searchBarButtonItems:(NSArray *)items forView:(UIView *)view storeItem:(UIBarButtonItem **)outItem {
for (UIBarButtonItem *item in items) {
if ([self ifBarButtonItem:item containsView:view storeItem:outItem])
return YES;
}
return NO;
}
+ (UIBarButtonItem *)barButtonItemForView:(UIView *)view {
id bar = view;
while (bar && !([bar isKindOfClass:[UIToolbar class]] || [bar isKindOfClass:[UINavigationBar class]])) {
bar = [bar superview];
}
if (!bar)
return nil;
UIBarButtonItem *item = nil;
if ([bar isKindOfClass:[UIToolbar class]]) {
[self searchBarButtonItems:[bar items] forView:view storeItem:&item];
}
else {
UINavigationItem *navItem = [bar topItem];
if (!navItem)
return nil;
[self ifBarButtonItem:navItem.backBarButtonItem containsView:view storeItem:&item]
|| [self ifBarButtonItem:navItem.leftBarButtonItem containsView:view storeItem:&item]
|| [self ifBarButtonItem:navItem.rightBarButtonItem containsView:view storeItem:&item]
|| ([navItem respondsToSelector:@selector(leftBarButtonItems)]
&& [self searchBarButtonItems:[(id)navItem leftBarButtonItems] forView:view storeItem:&item])
|| ([navItem respondsToSelector:@selector(rightBarButtonItems)]
&& [self searchBarButtonItems:[(id)navItem rightBarButtonItems] forView:view storeItem:&item]);
}
return item;
}
首先,你为什么需要访问UIBarButtonItem
?
然后,要创建一个带有自定义视图的UIBarButtonItem
,我建议您创建一个类别扩展,如下所示(在此情况下,自定义视图是一个UIButton
)。
//UIBarButtonItem+Extension.h
+ (UIBarButtonItem*)barItemWithImage:(UIImage*)image title:(NSString*)title target:(id)target action:(SEL)action;
//UIBarButtonItem+Extension.m
+ (UIBarButtonItem*)barItemWithImage:(UIImage*)image title:(NSString*)title target:(id)target action:(SEL)action
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
button.titleLabel.textAlignment = UITextAlignmentCenter;
[button setBackgroundImage:image forState:UIControlStateNormal];
[button setTitle:title forState:UIControlStateNormal];
[button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
return [barButtonItem autorelease];
}
使用方法如下(首先导入UIBarButtonItem+Extension.h
):
UIBarButtonItem* backBarButtonItem = [UIBarButtonItem barItemWithImage:[UIImage imageNamed:@"YoutImageName"] title:@"YourTitle" target:self action:@selector(doSomething:)];
在这里,选择器是一个在类(目标)内部实现的方法,该方法使用了该bar button item。
现在,在doSomething:
选择器中,您可以执行以下操作:
- (void)doSomething:(id)sender
UIButton* senderButton = (UIButton*)sender;
[popover presentPopoverFromRect:senderButton.bounds inView:senderButton...];
}
[popover presentPopoverFromRect:senderButton.bounds inView:senderButton...];'
这一行需要相当多的工作来重新定位弹出窗口,以适应旋转、键盘等。如果将弹出窗口从UIBarButtonItem中呈现,则可以消除所有这些问题,并始终将其锚定到UIBarButtonItem上。 - scooter133//Add a button on top of the UIBarButtonItem info_button
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[aButton addTarget:self action:@selector(showInfo:) forControlEvents:UIControlEventTouchUpInside];
info_Button.customView = aButton;
- (IBAction)showInfo:(id)sender
{
[self.flipsidePopoverController presentPopoverFromBarButtonItem:info_Button permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
不确定您是否需要UIButton。如果您要执行操作,甚至是使用图像自定义按钮,则UIBarButtonItem
应该足够。
如果您想从UIButton
中获取框架以实现演示效果,我认为您最好估计UIBarButtonItem
的位置。这不应该太困难,特别是如果它是您的UINavigationItem
的leftBarButtonItem
或rightBarButtonItem
之一。
我通常遵循KISS(保持简单,傻瓜!)的原则。即使是苹果也是如此...当您从Springboard启动应用程序时,应用程序总是从屏幕中心扩展,而不是从应用程序的图标扩展。
只是一个建议。
编辑
好的,我刚刚阅读了UIPopoverController reference(我从未使用过)。我认为你想要的是presentPopoverFromBarButtonItem:permittedArrowDirections:animated:
,并将你的BBI作为第一个参数传递进去。这个方法存在的原因就是为了解决你的问题——BBI没有框架,因为它们不是NSView的子类。苹果知道你想做这种事情,并提供了这个方法。此外,我认为如果你使用这个方法,你的自动旋转也会起作用。我可能错了,试试看吧。
至于你的自定义布局,我认为如果你在UIView中复制它,并使BBI与之自定义,效果会更好。当然,这取决于你自己。
无论哪种方式,你都可以通过将其连接为NIB的IBOutlet或在代码中创建时保存引用来获得对BBI的引用。然后只需将该引用传递给我上面描述的弹出窗口方法即可。我认为这可能适合你。
更多
BBI只是您类中的一个成员 - 一个iVar,它具有强引用属性,可能已链接到您的NIB作为IBOutlet。然后,您可以从类中的任何方法访问它。
示例:(不确定我是否正确处理了弹出控制器的内存管理)
@interface MyViewController : UIViewController {
UIBarButtonItem *item;
}
@property (nonatomic, retain) UIBarButtonItem *item;
@end
@implementation MyViewController
@synthesize item;
-(void)viewDidLoad {
// assuming item isn't in your NIB
item = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPlus target:self action:@selector(doit)];
self.navigationItem.rightBarButtonItem = item;
}
-(void)doit {
UIPopoverController *popover = [[[UIPopoverController alloc] initWithContentViewController:yourViewController] autorelease];
[popover presentPopoverFromBarButtonItem:self.item permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
// or in the line above, replace self.item with self.navigationItem.rightBarButtonItem
}
@end
UIBarButtonItem
与 UIButton
相连接,因为我现在有七个 UIBarButtonItem
。 - scooter133// get the UIBarButtonItem from the UIButton that is passed in sender
UIToolbar *toolbar = (id)[sender superview];
UIBarButtonItem *ourButtonItem = [toolbar items][2];//pick the right index
[parkingPopOver_ presentPopoverFromBarButtonItem:ourButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];