2012-02-29 8 views

Respuesta

9

Si ha establecido su UIButton como el customView de un UIBarButtonItem, o un niño de la vista personalizada, entonces se puede recorra la jerarquía de vista desde su botón hasta que encuentre el UIToolbar o el UINavigationBar que contiene el botón, luego busque los elementos de la barra para aquella cuya vista personalizada es el botón (o un antecesor del botón).

Aquí está mi código completamente no probado para hacer eso. Debería llamar al [[self class] barButtonItemForView:myButton] para obtener el artículo que contiene su botón.

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

¡Tú el hombre! No he podido probar NavigationItems porque estoy usando una UIToolBar. Esto funciona muy bien! ¡Gracias! – scooter133

6

En primer lugar, ¿por qué necesita acceder al UIBarButtonItem?

Luego, para crear un UIBarButtonItem con una vista personalizada, le sugiero que cree una extensión de categoría como la siguiente (en este caso, la vista personalizada es 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];  
} 

y el uso que como esta (primera importar UIBarButtonItem+Extension.h):

UIBarButtonItem* backBarButtonItem = [UIBarButtonItem barItemWithImage:[UIImage imageNamed:@"YoutImageName"] title:@"YourTitle" target:self action:@selector(doSomething:)]; 

donde el selector que es un método que se implementa dentro de la clase (el objetivo) que utiliza ese elemento botón de la barra.

Ahora dentro del selector de doSomething: se podía lo siguiente:

- (void)doSomething:(id)sender 

    UIButton* senderButton = (UIButton*)sender;  
    [popover presentPopoverFromRect:senderButton.bounds inView:senderButton...]; 
} 

Una categoría en este caso es útil no duplica código. Espero eso ayude.

P.S. No estoy usando ARC pero también se pueden aplicar las mismas consideraciones.

Editar:

Una solución fácil para acceder al elemento botón de la barra podrían ser los siguientes:

  1. Subclase un UIButton
  2. crear dentro de una propiedad de tipo UIBarButtonItem (uno débil para evitar retaincycle)
  3. Inyecte el elemento del botón de barra en el UIButton cuando lo crea.

Tal vez podría funcionar, pero preferiría el primero.

+0

tengo algo Similar a su código, aunque hice una Subclase de UIBarButtonItem ya que la apariencia del botón es bastante personalizada. El problema es '' popover presentPopoverFromRect: senderButton.bounds inView: senderButton ...]; ' Esto requiere bastante trabajo para re posicionar el popover luego de la rotación, el teclado, etc. Tener el popover presentado desde un UIBarButtonItem elimina todo eso y siempre se ancla al UIBarButtonItem. – scooter133

0

No estoy seguro de que necesite el UIButton. Si lo que estás haciendo es despachar una acción, o incluso personalizar el botón con una imagen, el UIBarButtonItem debería ser suficiente.

Si lo que persigue es agarrar el marco del UIButton para lograr la presentación, creo que sería mejor que simplemente estimar la posición del UIBarButtonItem. Esto no debería ser demasiado difícil, especialmente si es uno o el otro UINavigationItem 's leftBarButtonItem o rightBarButtonItem.

Generalmente soy para la regla de oro de KISS (Keep It Simple, Stupid!). Incluso Apple hace esto ... cuando inicias una aplicación desde Springboard, la aplicación siempre se expande desde el centro de la pantalla, no desde el ícono de la aplicación.

Solo una sugerencia.

EDITAR

bien, acabo de leer la UIPopoverController reference (nunca he utilizado uno). Creo que lo que quiere es presentPopoverFromBarButtonItem:permittedArrowDirections:animated: y pasar su BBI como primer parámetro. La razón por la que existe este método es para resolver su problema: los BBI no tienen marco porque no son subclases de NSView. Apple sabe que quieres hacer este tipo de cosas y proporciona este método. Además, creo que si usa este método, también funcionará su autorrotación. Puedo estar equivocado acerca de esto, darle una oportunidad.

Por lo que se refiere a su diseño personalizado, creo que si lo replicas en una UIView y haces la BBI personalizada con eso, lo harás mejor. Esto por supuesto depende de usted.

De cualquier forma, obtiene una referencia de BBI conectándola como IBOutlet con su NIB o guardando una referencia al crearla en el código. Luego solo pasa esa referencia al método popover que describí arriba. Creo que esto podría funcionar para ti.

MOAR

El BBI es sólo un miembro de la clase - una Ivar con una fuerte propiedad referencia en él, tal vez vinculado como un IBOutlet a su SEMILLA. Luego puede acceder desde cualquier método que desee en la clase.

Ejemplo: (no estoy seguro de que tengo el controlador de gestión de memoria popover derecha)

@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 
+0

El verdadero problema es mi Popover que se presenta de la acción del UIButton. Cuando giro la pantalla, el popover no está anclado al UIBarButtonItem, está anclado al marco del emisor de la acción, que es el UIButton. Necesitaba UIButton ya que mi UIToolBar es Personalizada, los botones son 84x48 en la parte inferior, 3 botones, espacio flexible, 4 botones.El UIButton me permite tener el BartButtonItem con un gráfico personalizado y una etiqueta en posiciones específicas en el 84x48. – scooter133

+0

Dado que los Popovers que se presentan desde BarButtonItems no tienen el problema de posicionamiento, pensé que podría hacer un sender.superView en el UIButton y obtener el UIBarButtonItem. en cambio, obtengo el UIToolBar. Tengo la posición del botón como una etiqueta, ¿puedo atravesar la UIToolBar para UIBarButtonItem? – scooter133

+0

hrms .... cuelgue uno – QED

0

Digamos que ha agregado el UIButton aButton a UIBarButtonItem info_button de la siguiente manera:

//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; 

Ahora, en showInfo, presentPopoverFromBarButtonItem: info_button (en lugar de presentPopoverFromBarButtonItem: emisor), esto pasará el info_button UIBarButtonItem para hacer pop sobre las obras:

- (IBAction)showInfo:(id)sender 
{ 
    [self.flipsidePopoverController presentPopoverFromBarButtonItem:info_Button permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; 

} 
0
// 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]; 
Cuestiones relacionadas