UIBarButtonItem avec image personnalisée et sans bordure

89

Je veux créer un UIBarButtonItem avec une image personnalisée, mais je ne veux pas de la bordure que l'iPhone ajoute, car mon image a une bordure spéciale.

C'est la même chose que le bouton retour mais un bouton avant.

Cette application est destinée à un projet inHouse, donc je m'en fiche si Apple la rejette, l'approuve ou l'aime :-)

Si j'utilise la propriété initWithCustomView: v de UIBarButtonItem, je peux le faire:

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

Cela fonctionne, mais si je dois répéter ce processus dans 10 vues, ce n'est pas DRY.

Je suppose que je dois sous-classer, mais quoi?

  • NSView?
  • UIBarButtonItem?

Merci,

Cordialement,

mongeta
la source
3
Merci d'avoir partagé votre code, c'est tout ce dont j'avais besoin :).
Max
1
Tout le monde, j'ai utilisé la réponse fournie par San le 6 février. Il a fallu 5 minutes pour s'intégrer dans mon Storyboard, et cela a parfaitement fonctionné. La propriété Selector se trouve sous l'inspecteur de connexions d'IB. Faites glisser le contrôle d'UIButton vers l'objet ViewController et les méthodes apparaîtront. Appuyez sur la méthode que vous souhaitez et vous avez pratiquement terminé. La seule chose qui reste serait un nettoyage du code. Utilisé btnXXXXX.hidden pour masquer et afficher pour remplacer barbuttonitem = nil. Mais cette méthode était simple et très propre.
user589642

Réponses:

44

Vous pouvez ajouter une méthode à UIBarButtonItem sans la sous-classer à l'aide de la catégorie personnalisée:

@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

Ainsi, n'importe où dans votre code, vous pouvez créer un élément de barre appelant cette méthode (à condition d'inclure un en-tête avec sa déclaration).

PS Vous n'avez pas besoin d'utiliser 'v' UIView car vous pouvez créer UIBarButtonItemdirectement avec un bouton comme vue personnalisée.
PPS Vous avez également besoin de [version avant] dans votre code.

Vladimir
la source
La catégorie personnalisée: je dois créer le fichier d'en-tête avec ces déclarations, et le fichier d'implémentation, où je mets le code que vous référez? merci
mongeta
Son travail merci beaucoup mais je ne suis pas capable d'écrire le sélecteur Je ne veux pas écrire le sélecteur sur la catégorie comment puis-je l'écrire sur ma classe
Nilesh Tupe
@NileshTupe que voulez-vous dire? Vous passez la méthode du sélecteur et la cible - donc la cible peut être l'objet de votre choix
Vladimir
2
BTW- J'ai ajouté cela à mon petit repo open source pour les catégories de commodité UIKit. Merci @Vladimir pour l'inspiration. (notez que tous mes trucs sont basés sur ARC) github.com/egold/UIKitConvenience/blob/master/UIKitConvenience
Eric Goldberg
50

Une autre solution simple est

  1. Faites glisser un UIButton standard
  2. Définissez le style du bouton sur personnalisé et définissez votre image pour ce bouton
  3. Faites-le glisser sur UINavigationBar
  4. Définir le sélecteur
san
la source
Probablement la solution la plus simple. Merci!
Prine
1
Brillant! La seule bizarrerie - cela ne fonctionnerait pas si vous faites glisser le bouton directement vers la barre de navigation. Le bouton doit être défini sur personnalisé avant d'être ajouté à la barre de navigation. Je ne sais pas pourquoi, mais c'est comme ça. Donc, étape # 1 - signifie faire glisser UIBatton quelque part sur votre interface utilisateur autre que la barre de navigation.
Andrei Tchijov
il est difficile d'être simple et efficace. Belle réponse
Add080bbA
37

J'ai trouvé cela facile. Il est suggéré par-dessus. "random.png" doit être dans le projet. Faites simplement glisser et déposez n'importe quelle image.

 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;
m-farhan
la source
6

Une alternative consiste à sous-classer UIBarButtonItem. Pourquoi? Pour que l'action soit appelée sur la cible avec l'expéditeur correct. Dans le code ci-dessus, l'argument de l'expéditeur dans le message d'action est l'instance UIButton, pas l'instance UIBarButtonItem. Cela serait important, par exemple, si vous souhaitez présenter un UIPopoverController à partir de l'élément du bouton de la barre. En sous-classant UIBarButtonItem, vous pouvez ajouter un ivar qui conserve la cible d'origine, permettant à nos instances de sous-classe d'intercepter, de modifier et de transmettre le message d'action avec l'expéditeur approprié.

Donc, CCFBarButtonItem.h:

#import <uIKit/UIBarButtonItem.h>

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

et 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
FluffulousChimp
la source
5
UIBarButtonItem *menuItem = [[UIBarButtonItem alloc] initWithImage: [UIImage imageNamed:@"icon-menu.png"]
                                                                    style:UIBarButtonItemStylePlain
                                                                   target:self
                                                                   action:@selector(showMenu)];
alexmorhun
la source
3

Cela peut également être fait par programme (bien sûr):

Commencez par créer une vue personnalisée. Cette vue personnalisée peut contenir une image, un bouton ou tout ce que vous souhaitez. La vue personnalisée peut être créée par programme ou dans 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];

Ensuite, créez un UIBarButtonItem et initialisez-le avec la vue personnalisée.

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

Maintenant, ajoutez simplement le UIBarButton personnalisé au leftBarButtonItem:

self.navigationItem.leftBarButtonItem = customBarButtonItem;
abriggs
la source
1

Ok cette catégorie fonctionne très bien car il n'y a aucun problème avec 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
Raegtime
la source
1

Découvrez cette solution simple.

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

Ici 1x1.png est une image png transparente de 1 pixel que vous pouvez télécharger à partir du lien ci-dessous

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

Fremy José
la source
Vous pouvez simplement utiliser [UIImage new] au lieu d'utiliser l'image transparente.
James Campbell
0

Une autre solution, pensez que c'est plus simple au cas où vous créez un bouton par programme:

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];
Mikhail
la source