UIBarButtonItem mit benutzerdefiniertem Bild und ohne Rand

89

Ich möchte ein UIBarButtonItem mit einem benutzerdefinierten Bild erstellen, aber ich möchte nicht den Rand, den das iPhone hinzufügt, da mein Bild einen speziellen Rand hat.

Es ist dasselbe wie die Zurück-Taste, aber eine Vorwärts-Taste.

Diese App ist für ein inHouse-Projekt gedacht, daher ist es mir egal, ob Apple sie ablehnt oder genehmigt oder mag :-)

Wenn ich die Eigenschaft initWithCustomView: v des UIBarButtonItem verwende, kann ich Folgendes tun:

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

Dies funktioniert, aber wenn ich diesen Vorgang in 10 Ansichten wiederholen muss, ist dies nicht trocken.

Ich nehme an, ich muss eine Unterklasse bilden, aber was?

  • NSView?
  • UIBarButtonItem?

Vielen Dank,

Grüße,

Mongeta
quelle
3
Danke, dass du deinen Code geteilt hast, das ist alles was ich brauchte :).
Max
1
Alle, ich habe die Antwort von San am 6. Februar verwendet. Die Integration in mein Storyboard dauerte 5 Minuten und funktionierte perfekt. Die Selector-Eigenschaft befindet sich unter Connections Inspector von IB. Wenn Sie das Ziehen von UIButton auf das ViewController-Objekt steuern, werden die Methoden angezeigt. Tippen Sie auf die gewünschte Methode und schon sind Sie fertig. Das einzige, was noch übrig wäre, wäre eine Code-Bereinigung. Verwendet btnXXXXX.hidden zum Ein- und Ausblenden, um barbuttonitem = nil zu ersetzen. Aber diese Methode war einfach und sehr sauber.
user589642

Antworten:

44

Sie können UIBarButtonItem eine Methode hinzufügen, ohne sie mithilfe einer benutzerdefinierten Kategorie zu unterordnen:

@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

Sie können also überall in Ihrem Code ein Balkenelement erstellen, das diese Methode aufruft (vorausgesetzt, Sie fügen der Deklaration einen Header hinzu).

PS Sie müssen 'v' UIView nicht verwenden, da Sie UIBarButtonItemmit einer Schaltfläche direkt als benutzerdefinierte Ansicht erstellen können.
PPS Sie benötigen außerdem [Forward Release] in Ihrem Code.

Vladimir
quelle
Die benutzerdefinierte Kategorie: Ich muss die Header-Datei mit diesen Deklarationen und die Implementierungsdatei erstellen, in die ich den Code eingefügt habe, auf den Sie sich beziehen. danke
mongeta
Seine Arbeit danke viel, aber ich bin nicht in der Lage, Selektor zu schreiben Ich möchte keinen Selektor auf Kategorie schreiben, wie kann ich es auf meine Klasse schreiben
Nilesh Tupe
@NileshTupe was meinst du? Sie übergeben Auswahlmethode und Ziel - so kann Ziel sein, welches Objekt Sie wollen
Vladimir
2
Übrigens: Ich habe dies zu meinem kleinen Open-Source-Repo für UIKit-Convenience-Kategorien hinzugefügt. Danke @Vladimir für die Inspiration. (Beachten Sie, dass alle meine Sachen ARC-basiert sind) github.com/egold/UIKitConvenience/blob/master/UIKitConvenience/…
Eric Goldberg
50

Eine andere einfache Lösung ist

  1. Ziehen Sie einen Standard-UIButton
  2. Stellen Sie den Stil der Schaltfläche auf "Benutzerdefiniert" und legen Sie Ihr Bild für diese Schaltfläche fest
  3. Ziehen Sie es auf die UINavigationBar
  4. Selektor einstellen
san
quelle
Wahrscheinlich die einfachste Lösung. Vielen Dank!
Prine
1
Brillant! Die einzige Besonderheit - es würde nicht funktionieren, wenn Sie die Schaltfläche direkt in die Navigationsleiste ziehen. Die Schaltfläche muss auf "Benutzerdefiniert" eingestellt werden, bevor sie zur Navigationsleiste hinzugefügt wird. Ich weiß nicht warum, aber so ist es. Schritt 1 bedeutet also, dass Sie UIBatton an eine andere Stelle als die Navigationsleiste ziehen.
Andrei Tchijov
Es ist schwer, einfach und effektiv zu sein. Schöne Antwort
Add080bbA
37

Ich fand es so einfach. Es wird oben gezuckert. "random.png" muss im Projekt sein. Ziehen Sie einfach ein Bild per Drag & Drop.

 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
quelle
6

Eine Alternative ist die Unterklasse UIBarButtonItem. Warum? Damit wird die Aktion auf dem Ziel mit dem richtigen Absender aufgerufen. Im obigen Code ist das Absenderargument in der Aktionsnachricht die UIButton-Instanz, nicht die UIBarButtonItem-Instanz. Dies ist beispielsweise wichtig, wenn Sie einen UIPopoverController über die Leistenschaltfläche präsentieren möchten. Durch Unterklassen von UIBarButtonItem können Sie einen ivar hinzufügen, der das ursprüngliche Ziel beibehält, sodass unsere Unterklasseninstanzen die Aktionsnachricht abfangen, ändern und an den richtigen Absender weiterleiten können.

Also, CCFBarButtonItem.h:

#import <uIKit/UIBarButtonItem.h>

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

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

Dies kann auch programmgesteuert erfolgen (natürlich):

Erstellen Sie zunächst eine benutzerdefinierte Ansicht. Diese benutzerdefinierte Ansicht kann ein Bild, eine Schaltfläche oder was auch immer Sie möchten enthalten. Die benutzerdefinierte Ansicht kann programmgesteuert oder in IB erstellt werden:

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

Erstellen Sie als Nächstes ein UIBarButtonItem und initialisieren Sie es mit der benutzerdefinierten Ansicht.

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

Fügen Sie jetzt einfach den benutzerdefinierten UIBarButton zum leftBarButtonItem hinzu:

self.navigationItem.leftBarButtonItem = customBarButtonItem;
Abkürzungen
quelle
1

Ok, diese Kategorie funktioniert sehr gut, da es keine Probleme mit Popovercontroller gibt :-)

#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
quelle
1

Schauen Sie sich diese einfache Lösung an.

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

Hier ist 1x1.png ein 1 Pixel transparentes PNG-Bild, das Sie über den unten stehenden Link herunterladen können

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

Fremy Jose
quelle
Sie können einfach [UIImage new] verwenden, anstatt das transparente Bild zu verwenden.
James Campbell
0

Eine andere Lösung, denken Sie, es ist einfacher, wenn Sie Schaltflächen programmgesteuert erstellen:

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
quelle