web-dev-qa-db-fra.com

Comment ajuster le rembourrage gauche et droit de UIToolBar

Je crée un UIToolbar avec du code et un autre avec le constructeur d'interface. Mais, découvrez les deux barres d’outils avec un rembourrage différent à gauche et à droite, illustrées ci-dessous:

De Interface Builder:

enter image description here

De code:

enter image description here

UIImage *buttonImage = [[UIImage imageNamed:@"button.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:0];
UIButton *btnTest = [UIButton buttonWithType:UIButtonTypeCustom];
[btnTest setBackgroundImage:buttonImage forState:UIControlStateNormal];
[btnTest setTitle:@"Back" forState:UIControlStateNormal];   
[btnTest.titleLabel setFont:[UIFont boldSystemFontOfSize:13]];  
[btnTest setBackgroundImage:[imgToolbarButton stretchableImageWithLeftCapWidth:5 topCapHeight:0]  forState:UIControlStateNormal];
[btnTest addTarget:self action:@selector(clearDateEdit:) forControlEvents:UIControlEventTouchUpInside];
btnTest.frame = CGRectMake(0.0, 0.0, 50, 30);
UIBarButtonItem *btnTestItem = [[UIBarButtonItem alloc] initWithCustomView:btnTest];
[self.toolbar setItems:[NSArray arrayWithObjects:btnTestItem,nil]];
[btnTestItem release];

Ma question est comment puis-je ajuster le remplissage gauche et à droite de UIToolbar par code?

Mettre à jour

J'ai découvert que ce problème d'alignement ne concernait que UIBarButtonItem avec customView of UIButton. L'alignement est correct avec UIBarButtonItem. Toute idée de ce qui cause ceci ou pour résoudre ceci.

La seule solution à laquelle je puisse penser maintenant est de définir manuellement le cadre.

57
TonyTakeshi

J'ai eu le même problème, et il y a une astuce que vous pouvez faire avec un UIBarButtonSystemItemFixedSpace, ajoutez un de ceux-ci avec une largeur négative avant votre premier bouton et après votre dernier bouton et cela déplacera le bouton vers Edge.

Par exemple, pour supprimer la marge de droite, ajoutez l'élément de barre FixedSpace suivant au dernier élément:

UIBarButtonItem *negativeSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
negativeSeparator.width = -12;

Les marges à gauche et à droite sont 12px.

Mise à jour pour iOS7 - les marges sont de 16 pixels sur iPhone et de 20 pixels sur iPad!

148
Craig Mellon

Avant iOS 11

Vous avez eu trois solutions possibles:

  • La première utilisait un élément d'espace fixe UIBarButtonItem (barButtonSystemItem: .fixedSpace…) avec une largeur négative.
  • L'autre consistait à substituer alignmentRectInsets dans la vue personnalisée.
  • Le dernier, si vous utilisez UIButton en tant que vue personnalisée de votre élément, vous pouvez remplacer contentEdgeInsets et hitTest (_: with :)

Absolument, la première solution semble meilleure que les autres

UIBarButtonItem *negativeSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
negativeSeparator.width = -12;

si vous utilisez Swift, le code ressemblera à ceci

var negativeSeparator = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
negativeSeparator.width = -12

Après iOS 11 (contient iOS 11)

malheureusement, toute la solution ne peut pas être utilisée dans iOS 11 

  • première solution: définir une largeur négative ne fonctionne plus
  • deuxième solution: remplacer l 'alignementRectInsets causera qu'une partie de l' objet ne reçoit plus de contacts
  • la dernière solution: je pense que remplacer hitTest (_: avec :) n'est pas une bonne idée, ne faites pas cela s'il vous plaît!

Vous pouvez également voir quelques suggestions sur les forums de développeurs , mais après avoir consulté tous les commentaires, vous trouverez une suggestion à ce sujet: créer une sous-classe UINavigationBar personnalisée et faire quelque chose de complexe.

Oh mon dieu, tout ce que je veux, c'est changer le rembourrage, pas la barre de navigation! 

Heureusement, nous pouvons le faire avec une astuce dans iOS 11!

Et c'est parti:

1. créer un bouton personnalisé

  • set translatesAutoresizingMaskIntoConstraints comme false
  • remplacez alignmentRectInsets
    • l'élément dans le côté droit utilise UIEdgeInsets (en haut: 0, à gauche: -8, en bas: 0, à droite: 8)
    • élément du côté gauche, utilisez UIEdgeInsets (haut: 0, gauche: 8, bas: 0, droite: -8)

      si vous ne connaissez pas alignmentRectInsets, vous pouvez lire CE BLOG en premier

Version rapide

var customButton = UIButton(type: .custom)
customButton.overrideAlignmentRectInsets = UIEdgeInsets(top: 0, left: x, bottom: 0, right: -x) // you should do this in your own custom class
customButton.translatesAutoresizingMaskIntoConstraints = false;

version objective-c

UIButton *customButton = [UIButton buttonWithType:UIButtonTypeCustom];
customButton.overrideAlignmentRectInsets = UIEdgeInsetsMake(0, x, 0, -x); // you should do this in your own custom class
customButton.translatesAutoresizingMaskIntoConstraints = NO;

2. créer un article avec votre bouton personnalisé

Version rapide

var item = UIBarButtonItem(customView: customButton)

version objective-c

UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:customButton]

3. créer un UIBarButtonItem de type fixedSpace avec positive width

définir une valeur positive et non une valeur négative

Version rapide

var positiveSeparator = UIBarButtonItem(barButtonSystemItem:.fixedSpace, target: nil, action: nil)
positiveSeparator.width = 8

version objective-c

UIBarButtonItem *positiveSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
positiveSeparator.width = 8;

4. définir un tableau sur leftitems ou rightitems

fixedSpace type L'élément UIBarButton doit être le premier élément du tableau.

Version rapide

self.navigationItem.leftBarButtonItems = [positiveSeparator, item, ...]

version objective-c

self.navigationItem.leftBarButtonItems = @{positiveSeparator, item, ...}

Bien joué

après avoir suivi toutes les étapes, vous constaterez que votre rembourrage devient plus petit et que la zone de frappe semble correcte!

Si vous trouvez quelque chose qui ne va pas, s'il vous plaît faites le moi savoir! Je ferai de mon mieux pour répondre à votre question!

Remarque

Avant iOS 11, vous devriez vous préoccuper de la largeur de l'écran de l'appareil. si l'écran est de 5,5 pouces, le négatif est de -12 points, sur les autres écrans de -8 points.

Si vous utilisez ma solution sur iOS 11, vous n'avez pas besoin de vous soucier de l'écran du périphérique, définissez simplement 8 pt, Vous devez vous soucier de la position de l'élément dans la barre de navigation, à gauche ou à droite, cela affectera votre vue personnalisée. alignementRectInsets

Vouloir plus de zone de robinet

Si vous souhaitez promettre que votre zone de prise est supérieure à 44 * 44, vous pouvez remplacer la méthode ci-dessous.

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
    CGSize acturalSize = self.frame.size;
    CGSize minimumSize = kBarButtonMinimumTapAreaSize;
    CGFloat verticalMargin = acturalSize.height - minimumSize.height >= 0 ? 0 : ((minimumSize.height - acturalSize.height ) / 2);
    CGFloat horizontalMargin = acturalSize.width - minimumSize.width >= 0 ? 0 : ((minimumSize.width - acturalSize.width ) / 2);
    CGRect newArea = CGRectMake(self.bounds.Origin.x - horizontalMargin, self.bounds.Origin.y - verticalMargin, self.bounds.size.width + 2 * horizontalMargin, self.bounds.size.height + 2 * verticalMargin);
    return CGRectContainsPoint(newArea, point);
}
19
SketchK

C'est une excellente question et même avec les solutions fournies - cela n'a pas résolu le problème sur iOS11.

SOLUTION DE TRAVAIL

Si vous créez une nouvelle extension de UIButton:

class BarButton: UIButton {

    override var alignmentRectInsets: UIEdgeInsets {
        return UIEdgeInsetsMake(0, 16, 0, 16)
    }

}

Ensuite, lorsque vous l'utilisez dans votre mise en page:

lazy var btnLogin: BarButton = {
    let btn = BarButton(type: .custom)
    // Add your button settings

    btn.widthAnchor.constraint(equalToConstant: self.frame.size.width).isActive = true
    btn.heightAnchor.constraint(equalToConstant: 50).isActive = true
    btn.translatesAutoresizingMaskIntoConstraints = false
    return btn
}()

Cela a résolu un problème très ennuyant, si vous avez des problèmes, faites-le moi savoir.

6
RichAppz

utiliser ce bouton

UIBarButtonItem *spaceItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
                                                                           target:nil
                                                                           action:nil];
3
Madhu

Vous pouvez modifier le décalage et la largeur de votre barre d’outils si vous voulez utiliser customview (initWithCustomView). 

[myToolBar setFrame:CGRectMake(-10, 0, [UIScreen mainScreen].bounds.size.width+10, 44)];
2
Mihriban Minaz

Je suis tombé sur cela en essayant de centrer une barre d'outils comme une sous-vue d'un UIButton. Comme la barre d’outils devait être de faible largeur, la meilleure solution consistait en un bouton flexible de chaque côté: 

UIBarButtonItem flexibleButtonItemLeft = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];

UIBarButtonItem centeredButtonItem = ...

UIBarButtonItem flexibleButtonItemRight = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];

UIToolbar toolbar = ...

toolbar.items = @[flexibleButtonItemLeft, centeredButtonItem, flexibleButtonItemRight];
2
Karmeye

J'ai rencontré le même problème. Enfin, j'ai résolu ce problème en sous-classant UIToolbar et en remplaçant la méthode de présentation des sous-vues. 

- (void)layoutSubviews {

  [super layoutSubviews];

  if (leftItem_ && leftItem_.customView
      && [leftItem_.customView isKindOfClass:[UIButton class]]) {
    CGRect newFrame = leftItem_.customView.frame;
    newFrame.Origin.x = 0;   // reset the original point x to 0; default is 12, wired number
    leftItem_.customView.frame = newFrame;    
  }

  if (rightItem_ && rightItem_.customView
      && [rightItem_.customView isKindOfClass:[UIButton class]]) {
    CGRect newFrame = rightItem_.customView.frame;
    newFrame.Origin.x = self.frame.size.width - CGRectGetWidth(newFrame);
    rightItem_.customView.frame = newFrame;
  }

}
2
Fourj

Je pense qu'un moyen délicat consiste à utiliser Aspects (ou méthode swizzling), comme indiqué

[UINavigationBar aspect_hookSelector:@selector(layoutSubviews) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> info){
        UINavigationBar *bar = info.instance;

        //[bar layoutSubviews];

        if ([bar isKindOfClass:[UINavigationBar class]]) {
            if (@available(iOS 11, *)) {
                bar.layoutMargins = UIEdgeInsetsZero;

                for (UIView *subview in bar.subviews) {
                    if ([NSStringFromClass([subview class]) containsString:@"ContentView"]) {
                        UIEdgeInsets oEdges = subview.layoutMargins;
                        subview.layoutMargins = UIEdgeInsetsMake(0, 0, 0, oEdges.right);
                    }
                }
            }
        }
    } error:nil];
0
ekingo Hu

Juste ajoutez des constantes négatives à votre contraintes de début et de fin de la UIToolbar. De cette façon, la barre d'outils commence et se termine en dehors de votre vue et a donc moins de remplissage.

0
fl034

Enfin, pour avoir personnalisé l’image d’arrière-plan de UIBarButtonItem et permettre l’alignement, j’ai abandonné UIBarButtonItem et ajouté manuellement UIButton.

UIImage *buttonImage = [[UIImage imageNamed:@"button.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:0];
UIButton *btnTest = [UIButton buttonWithType:UIButtonTypeCustom];
[btnTest setBackgroundImage:buttonImage forState:UIControlStateNormal];
[btnTest setTitle:@"Back" forState:UIControlStateNormal];   
[btnTest.titleLabel setFont:[UIFont boldSystemFontOfSize:13]];  
[btnTest setBackgroundImage:[imgToolbarButton stretchableImageWithLeftCapWidth:5 topCapHeight:0]  forState:UIControlStateNormal];
[btnTest addTarget:self action:@selector(clearDateEdit:) forControlEvents:UIControlEventTouchUpInside];
btnTest.frame = CGRectMake(0.0, 0.0, 50, 30);
[self.toolbar addSubview:btnTest];
[btnTestItem release];
0
TonyTakeshi