web-dev-qa-db-fra.com

rembourrage excessif des boutons de la barre de navigation iOS 7

Je rencontre un espacement/remplissage excessif UIBarButtonItem lors de l'utilisation des éléments LeftBarItems et RightBarItems (voir l'image ci-dessous). Les icônes utilisées sur les UIBarButtonItems ne contiennent pas de remplissage supplémentaire. Donc, j'aimerais savoir ce qui cause cela?

enter image description here

46
Oliver Weichhold

J'utilise ceci afin de supprimer de l'espace avant le premier élément.

Cependant, cela ne fonctionne pas entre les éléments système comme UIBarButtonSystemItemAdd, uniquement avec UIBarButtonItem qui a une image.

@interface UIBarButtonItem (NegativeSpacer)
+(UIBarButtonItem*)negativeSpacerWithWidth:(NSInteger)width;
@end
@implementation UIBarButtonItem (NegativeSpacer)
+(UIBarButtonItem*)negativeSpacerWithWidth:(NSInteger)width {
    UIBarButtonItem *item = [[UIBarButtonItem alloc]
                             initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
                             target:nil
                             action:nil];
    item.width = (width >= 0 ? -width : width);
    return item;
}
@end

Utilisez-le comme ceci:


UIBarButtonItem *item0 = [UIBarButtonItem negativeSpacerWithWidth:13];
UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"sidebar.png"]
                                                          style:UIBarButtonItemStylePlain
                                                         target:vc
                                                         action:@selector(sideMenuAction:)];
NSArray* items = @[item0, item1];
[vc.navigationItem setLeftBarButtonItems:items animated:NO];
[vc.navigationItem setLeftItemsSupplementBackButton:YES];
27
neoneye

Vous pouvez déplacer l'image 

self.myBarButtonItem.imageInsets = UIEdgeInsetsMake(0, 25, 0, -25);
25
Luda

Apple a augmenté silencieusement les contraintes d'espacement horizontal pour UIBarButtonItems et, malheureusement, n'a toujours pas ajouté de méthode UIAppearance pour ajuster le positionnement horizontal de UIBarButtonItems.

La meilleure solution (qui a fonctionné pour moi) consiste à envelopper vos UIBarButtonItems dans une vue UIV à l’aide de initWithCustomView: et à ajuster les limites de cette vue personnalisée pour obtenir le positionnement souhaité. Voici une bonne réponse sur la façon de faire cela .

Si vous voulez aller plus loin, vous pouvez créer une catégorie sur UIBarButtonItem avec des méthodes de classe qui renvoient les boutons de barre que vous utilisez dans votre application. De cette façon, lorsque vous avez besoin d’un bouton de barre, vous pouvez appeler quelque chose comme:

self.navigationItem.leftBarButtonItem = [UIBarButtonItem mySearchBarButtonItemWithTarget:self selector:@selector(search)];
8
Wes Dearborn

Il existe deux types de bouton dans la barre de navigation dans iOS 7: le bouton avec image et le bouton avec texte. J'ai écrit un cours pour le faire. Voici comment:

GlobalUICommon.h:

@interface UIBarButtonItem(CustomUIOfONE)

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

+ (UIBarButtonItem*)barItemWithTitle:(NSString*)title xOffset:(NSInteger)xOffset target:(id)target action:(SEL)action;

@end

GlobalUICommon.m:

@implementation UIBarButtonItem(CustomUIOfONE)

+ (UIBarButtonItem*)barItemWithImage:(UIImage*)image highlightedImage:(UIImage*)highlightedImage xOffset:(NSInteger)xOffset target:(id)target action:(SEL)action
{
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button setFrame:CGRectMake(0, 0, image.size.width, image.size.height)];
    [button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
    [button setImage:image forState:UIControlStateNormal];
    [button setImage:highlightedImage forState:UIControlStateHighlighted];
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
        [button setImageEdgeInsets:UIEdgeInsetsMake(0, xOffset, 0, -xOffset)];
    }

    UIBarButtonItem *customUIBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
    return customUIBarButtonItem;
}

+ (UIBarButtonItem*)barItemWithTitle:(NSString*)title xOffset:(NSInteger)xOffset target:(id)target action:(SEL)action
{
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button setTitle:title forState:UIControlStateNormal];
    [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [button setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
    [button.titleLabel setFont:[UIFont systemFontOfSize:15]];
    [button setFrame:CGRectMake(0, 0, [button.titleLabel.text sizeWithFont:button.titleLabel.font].width + 3, 24)];
    [button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
        [button setContentEdgeInsets:UIEdgeInsetsMake(0, xOffset, 0, -xOffset)];
    }

    UIBarButtonItem *customUIBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
    return customUIBarButtonItem;
}

@end

YourViewController.m:

Exemple de bouton avec image:

UIBarButtonItem* leftButtomItem = [UIBarButtonItem barItemWithImage:[UIImage imageNamed:@"yourImage"]
                                                   highlightedImage:[UIImage imageNamed:@"yourImage"]
                                                            xOffset:-11
                                                             target:self
                                                             action:@selector(yourHandler)];
self.navigationItem.leftBarButtonItem = leftButtomItem;
UIBarButtonItem* rightButtonItem = [UIBarButtonItem barItemWithImage:[UIImage imageNamed:@"yourImage"]
                                                   highlightedImage:[UIImage imageNamed:@"yourImage"]
                                                            xOffset:11
                                                             target:self
                                                             action:@selector(yourHandler)];
self.navigationItem.rightBarButtonItem = rightButtonItem;

Exemple pour bouton avec texte:

self.navigationItem.leftBarButtonItem = [UIBarButtonItem barItemWithTitle:@"yourText" xOffset:-11 target:self action:@selector(yourHandler:)];
self.navigationItem.rightBarButtonItem = [UIBarButtonItem barItemWithTitle:@"yourText" xOffset:11 target:self action:@selector(yourHandler:)];

C'est tout.

7
itisalex

J'ai résolu ce problème en utilisant l'interface Storybord.

1.Sélectionnez le Bar item.

2.Sélectionnez le Size Inspector.

Ici vous pouvez trouver une image insérée, en utilisant top, bottom ET left, right vous pouvez changer la position de l'élément de barre.

2
jithin

Comme @Luda commente, la solution consiste à 

self.myBarButtonItem.imageInsets = UIEdgeInsetsMake(0, 25, 0, -25);

Cependant, @andrrs signale également un problème lorsque l'insert est grand: la zone touchée. Dans ce cas, nous devons implémenter un moyen de setHitTestEdgeInsets. Ci-dessous une méthode de catégorie:

@implementation UIButton (Extensions)

@dynamic hitTestEdgeInsets;

static const NSString *KEY_HIT_TEST_Edge_INSETS = @"HitTestEdgeInsets";

-(void)setHitTestEdgeInsets:(UIEdgeInsets)hitTestEdgeInsets {
    NSValue *value = [NSValue value:&hitTestEdgeInsets withObjCType:@encode(UIEdgeInsets)];
    objc_setAssociatedObject(self, &KEY_HIT_TEST_Edge_INSETS, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(UIEdgeInsets)hitTestEdgeInsets {
    NSValue *value = objc_getAssociatedObject(self, &KEY_HIT_TEST_Edge_INSETS);
    if(value) {
        UIEdgeInsets edgeInsets; [value getValue:&edgeInsets]; return edgeInsets;
    }else {
        return UIEdgeInsetsZero;
    }
}

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    if(UIEdgeInsetsEqualToEdgeInsets(self.hitTestEdgeInsets, UIEdgeInsetsZero) ||       !self.enabled || self.hidden) {
        return [super pointInside:point withEvent:event];
    }

    CGRect relativeFrame = self.bounds;
    CGRect hitFrame = UIEdgeInsetsInsetRect(relativeFrame, self.hitTestEdgeInsets);

    return CGRectContainsPoint(hitFrame, point);
}

@end
0
Jacky