UIBarButtonItem con immagine personalizzata e nessun bordo


89

Voglio creare un UIBarButtonItem con un'immagine personalizzata, ma non voglio il bordo aggiunto da iPhone, poiché la mia immagine ha un bordo speciale.

È lo stesso del pulsante Indietro ma di un pulsante Avanti.

Questa App è per un progetto inHouse, quindi non mi interessa se Apple la rifiuta, la approva o mi piace :-)

Se utilizzo la proprietà initWithCustomView: v di UIBarButtonItem, posso farlo:

UIImage *image = [UIImage imageNamed:@"right.png"];

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage: [image stretchableImageWithLeftCapWidth:7.0 topCapHeight:0.0] forState:UIControlStateNormal];
[button setBackgroundImage: [[UIImage imageNamed: @"right_clicked.png"] stretchableImageWithLeftCapWidth:7.0 topCapHeight:0.0] forState:UIControlStateHighlighted];

 button.frame= CGRectMake(0.0, 0.0, image.size.width, image.size.height);

[button addTarget:self action:@selector(AcceptData)    forControlEvents:UIControlEventTouchUpInside];

UIView *v=[[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, image.size.width, image.size.height) ];

[v addSubview:button];

UIBarButtonItem *forward = [[UIBarButtonItem alloc] initWithCustomView:v];

self.navigationItem.rightBarButtonItem= forward;

[v release];
[image release];

Funziona, ma se devo ripetere questo processo in 10 visualizzazioni, non è DRY.

Suppongo di dover sottoclassare, ma cosa?

  • NSView?
  • UIBarButtonItem?

Grazie,

Saluti,


3
Grazie per aver condiviso il tuo codice, è tutto ciò di cui avevo bisogno :).
Max

1
Tutti, ho usato la risposta fornita da San il 6 febbraio. Ci sono voluti 5 minuti per integrarli nel mio Storyboard e ha funzionato perfettamente. La proprietà Selector si trova in Connections Inspector di IB. Trascina il controllo da UIButton all'oggetto ViewController e verranno visualizzati i metodi. Tocca il metodo che desideri e hai praticamente finito. L'unica cosa rimasta sarebbe stata una pulizia del codice. Usato btnXXXXX.hidden per nascondere e mostrare per sostituire barbuttonitem = nil. Ma questo metodo era semplice e molto pulito.
user589642

Risposte:


44

Puoi aggiungere un metodo a UIBarButtonItem senza sottoclassarlo utilizzando la categoria personalizzata:

@interface UIBarButtonItem(MyCategory)

+ (UIBarButtonItem*)barItemWithImage:(UIImage*)image target:(id)target action:(SEL)action;

@end

@implementation UIBarButtonItem(MyCategory)

+ (UIBarButtonItem*)barItemWithImage:(UIImage*)image target:(id)target action:(SEL)action{
 // Move your item creation code here
}
@end

Quindi ovunque nel tuo codice puoi creare un elemento bar chiamando questo metodo (a condizione che tu includa un'intestazione con la sua dichiarazione).

PS Non è necessario utilizzare UIView "v" poiché è possibile creare direttamente UIBarButtonItemcon un pulsante come visualizzazione personalizzata.
PPS Hai anche bisogno di [release forward] nel tuo codice.


La categoria personalizzata: devo creare il file di intestazione con quelle dichiarazioni e il file di implementazione, dove metto il codice a cui fai riferimento? grazie
mongeta

Funziona molto grazie ma non sono in grado di scrivere selettore non voglio scrivere selettore sulla categoria come posso scriverlo sulla mia classe
Nilesh Tupe,

@NileshTupe cosa intendi? Passi il metodo di selezione e il target, quindi il target può essere qualsiasi oggetto desideri
Vladimir

2
BTW- L'ho aggiunto al mio piccolo repository open source per le categorie di convenienza UIKit. Grazie @Vladimir per l'ispirazione. (nota che tutte le mie cose sono basate su ARC) github.com/egold/UIKitConvenience/blob/master/UIKitConvenience/…
Eric Goldberg

50

Un'altra semplice soluzione è

  1. Trascina un pulsante UIB standard
  2. Imposta lo stile del pulsante su personalizzato e imposta la tua immagine per quel pulsante
  3. Trascinalo sulla UINavigationBar
  4. Imposta selettore

Probabilmente la soluzione più semplice. Grazie!
Prine

1
Brillante! L'unica stranezza: non funzionerebbe se trascini il pulsante direttamente sulla barra di navigazione. Il pulsante deve essere impostato su personalizzato prima di essere aggiunto alla barra di navigazione. Non so perché, ma è così. Quindi il passaggio n. 1 significa trascinare UIBatton da qualche parte sull'interfaccia utente diversa dalla barra di navigazione.
Andrei Tchijov

è difficile essere semplici ed efficaci. Bella risposta
Add080bbA

37

L'ho trovato così facile. È zuccherato in cima. "random.png" deve essere nel progetto. Basta trascinare e rilasciare qualsiasi immagine.

 UIButton *a1 = [UIButton buttonWithType:UIButtonTypeCustom];
        [a1 setFrame:CGRectMake(0.0f, 0.0f, 25.0f, 25.0f)];
        [a1 addTarget:self action:@selector(randomMsg) forControlEvents:UIControlEventTouchUpInside];
        [a1 setImage:[UIImage imageNamed:@"config.png"] forState:UIControlStateNormal];
        UIBarButtonItem *random = [[UIBarButtonItem alloc] initWithCustomView:a1];

 //? line incomplete ?//   imageNamed:@"random.png"] style:UIBarButtonItemStylePlain target:self action:@selector(randomMsg)];

    self.navigationItem.rightBarButtonItem = random;

6

Un'alternativa è la sottoclasse UIBarButtonItem. Perché? In modo che l'azione venga richiamata sulla destinazione con il mittente corretto. Nel codice precedente, l'argomento del mittente nel messaggio di azione è l'istanza di UIButton, non l'istanza di UIBarButtonItem. Ciò sarebbe importante, ad esempio, se desideri presentare un UIPopoverController dalla voce del pulsante della barra. Creando una sottoclasse UIBarButtonItem, è possibile aggiungere un ivar che mantiene la destinazione originale, consentendo alle nostre istanze di sottoclasse di intercettare, modificare e inoltrare il messaggio di azione con il mittente appropriato.

Quindi, CCFBarButtonItem.h:

#import <uIKit/UIBarButtonItem.h>

@interface CCFBarButtonItem : UIBarButtonItem
{
@protected
    id _originalTarget;
}
- (id)initWithImage:(UIImage *)image target:(id)target action:(SEL)action;
@end

e CCFBarButtonItem.m

#import "CCFBarButtonItem.h"
#import <UIKit/UIButton.h>
#import <UIKit/UIView.h>
#import <UIKit/UIImage.h>

@implementation CCFBarButtonItem

#pragma mark - Object life cycle

- (id)initWithImage:(UIImage *)image target:(id)target action:(SEL)action;
{
    _ASSIGN( _originalTarget, target );

    UIButton *imgButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [imgButton setImage:image forState:UIControlStateNormal];
    imgButton.frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
    [imgButton addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];

    self = [super initWithCustomView:imgButton];

    return self;
}

- (void)dealloc;
{
    MCRelease(_originalTarget);
    [super dealloc];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
{
    if( [_originalTarget respondsToSelector:aSelector] )
    {
        return [_originalTarget methodSignatureForSelector:aSelector];
    }
    else
    {
        return [super methodSignatureForSelector:aSelector];
    }
}

- (void)forwardInvocation:(NSInvocation *)anInvocation;
{
    SEL aSelector = [anInvocation selector];
    if( [_originalTarget respondsToSelector:aSelector] )
    {
        //  modify the 'sender' argument so that it points to self
        [anInvocation setArgument:&self atIndex:2];
        [anInvocation invokeWithTarget:_originalTarget];
    }
    else
    {
        [self doesNotRecognizeSelector:aSelector];
    }
}
@end

5
UIBarButtonItem *menuItem = [[UIBarButtonItem alloc] initWithImage: [UIImage imageNamed:@"icon-menu.png"]
                                                                    style:UIBarButtonItemStylePlain
                                                                   target:self
                                                                   action:@selector(showMenu)];

3

Questo può anche essere fatto a livello di programmazione (ovviamente):

Innanzitutto, crea una visualizzazione personalizzata. Questa visualizzazione personalizzata può contenere un'immagine, un pulsante o qualsiasi altra cosa desideri. La visualizzazione personalizzata può essere creata in modo programmatico o in IB:

UIImage *customImage = [UIImage imageNamed:@"imageName"];
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, customImage.size.width, customImage.size.height)];
customView.backgroundColor = [UIColor colorWithPatternImage:customImage];

Successivamente, crea un UIBarButtonItem e inizializzalo con la visualizzazione personalizzata.

UIBarButtonItem *customBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:customView];

Ora, aggiungi semplicemente l'UIBarButton personalizzato a leftBarButtonItem:

self.navigationItem.leftBarButtonItem = customBarButtonItem;

1

Ok, quella categoria funziona molto bene perché non ci sono problemi con il Popovercontroller :-)

#import <UIKit/UIKit.h>

@interface UIBarButtonItem (BarButtonItemExtended)
+ (UIBarButtonItem*)barItemWithImage:(UIImage*)image target:(id)target action:(SEL)action;
-(void)performBarButtonAction:(id)sender;
@end



#import "UIBarButtonItem+BarButtonItemExtended.h"

@implementation UIBarButtonItem (BarButtonItemExtended)

+ (UIBarButtonItem*)barItemWithImage:(UIImage*)image target:(id)target action:(SEL)action
{    
    UIButton *imgButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [imgButton setImage:image forState:UIControlStateNormal];
    imgButton.frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);

    UIBarButtonItem *b = [[UIBarButtonItem alloc]initWithCustomView:imgButton];

    [imgButton addTarget:b action:@selector(performBarButtonAction:) forControlEvents:UIControlEventTouchUpInside];

    [b setAction:action];
    [b setTarget:target];

    return b;
}

-(void)performBarButtonAction:(UIButton*)sender
{
    [[self target] performSelector:self.action withObject:self];
}
@end

1

Dai un'occhiata a questa semplice soluzione.

- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
barButtonItem.image = [UIImage imageNamed:@"navButton.png"];
barButtonItem.style = UIBarButtonItemStylePlain;

[barButtonItem setBackgroundImage:[UIImage imageNamed:@"1x1.png"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
self.masterPopoverController = popoverController;
}

Qui 1x1.png è un'immagine png trasparente da 1 pixel che puoi scaricare dal link sottostante

http://commons.wikimedia.org/wiki/File:1x1.png


Potresti semplicemente usare [UIImage new] invece di usare l'immagine trasparente.
James Campbell

0

Un'altra soluzione, pensa che sia più semplice nel caso in cui si crei un pulsante in modo programmatico:

UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithImage:defaultImage
                                             landscapeImagePhone:landscapeImage
                                                           style:UIBarButtonItemStylePlain
                                                          target:self
                                                          action:@selector(someSelector)];
[button setBackgroundImage:[UIImage new] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[button setBackgroundImage:[UIImage new] forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone];
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.