iOS 11 UINavigationBar éléments du bouton Bar alignement
je mets à jour mon application en iOS 11 et je vois des problèmes avec la barre de navigation, une partie de mes problèmes ont déjà posé des questions ici, donc je ne vais pas les mentionner dans cette question.
le problème particulier en question Est que les éléments de la barre de navigation sont espacés différemment. Mes principaux boutons de gauche et de droite sont plus près du centre horizontal de l'écran maintenant et je ne peux pas les déplacer près des bords de l'écran. Dans le passé, j'ai utilisé un personnalisé UIButton
sous-classe et créé des éléments de bouton à barre avec vue personnalisée. La solution d'alignement était alignmentRectInsets
et <!-Je n'ai pas réussi à produire les résultats escomptés en utilisant cette approche.
Edit:
J'ai réessayé avec iOS 11 beta 2 et le problème persiste.
Edit 2: J'ai réessayé avec iOS beta 3 et le problème persiste.
9 réponses
Il existe un bon article sur ceci : http://www.matrixprojects.net/p/uibarbuttonitem-ios11/
en utilisant ceci nous pouvons au moins push rightbarbuttonitems à droite jusqu'à ce qu'il laisse une marge de 8 pixels à partir de la barre D'UINavigationBar.
très bien expliqué.
maintenant dans iOS 11 Vous pouvez gérer UINavigationBarContentView pour ajuster les contraintes de gauche et de droite, et UIStackView pour ajuster les boutons (ou d'autres éléments).
C'est ma solution pour une barre de navigation avec les éléments à gauche et à droite. Aussi il fixe si vous avez plusieurs boutons sur le côté.
- (void) updateNavigationBar {
for(UIView *view in self.navigationBar.subviews) {
if ([NSStringFromClass([view class]) containsString:@"ContentView"]) {
// Adjust left and right constraints of the content view
for(NSLayoutConstraint *ctr in view.constraints) {
if(ctr.firstAttribute == NSLayoutAttributeLeading || ctr.secondAttribute == NSLayoutAttributeLeading) {
ctr.constant = 0.f;
} else if(ctr.firstAttribute == NSLayoutAttributeTrailing || ctr.secondAttribute == NSLayoutAttributeTrailing) {
ctr.constant = 0.f;
}
}
// Adjust constraints between items in stack view
for(UIView *subview in view.subviews) {
if([subview isKindOfClass:[UIStackView class]]) {
for(NSLayoutConstraint *ctr in subview.constraints) {
if(ctr.firstAttribute == NSLayoutAttributeWidth || ctr.secondAttribute == NSLayoutAttributeWidth) {
ctr.constant = 0.f;
}
}
}
}
}
}
}
Comme vous le voyez il n'est pas nécessaire d'ajouter d'autres contraintes, comme d'autres personnes l'ont fait. Il y a déjà des contraintes bien définies, donc elles peuvent être modifié.
après environ deux jours, voici la solution la plus simple et la plus sûre que je puisse trouver. Cette solution ne fonctionne qu'avec les boutons de barre de vue personnalisés, dont le code est inclus. Il est important de noter que les marges Gauche et droite de la barre de navigation n'ont pas changé de iOS10 à iOS11 - elles sont toujours de 16px. Une telle marge importante rend difficile d'avoir une région de clic suffisamment grande.
les boutons de la barre sont maintenant disposés avec ceux D'UIStackView. La méthode antérieure de déplacer ces boutons plus près de la marge implique l'utilisation d'espaces fixes négatifs que ces vues stack ne peuvent pas gérer.
Sous-Classe UINavigationBar
FWNavigationBar.h
@interface FWNavigationBar : UINavigationBar
@end
FWNavigationBar.m
#import "FWNavigationBar.h"
@implementation FWNavigationBar
- (void)layoutSubviews {
[super layoutSubviews];
if (@available(iOS 11, *)) {
self.layoutMargins = UIEdgeInsetsZero;
for (UIView *subview in self.subviews) {
if ([NSStringFromClass([subview class]) containsString:@"ContentView"]) {
subview.layoutMargins = UIEdgeInsetsZero;
}
}
}
}
@end
en utilisant le contrôleur D'Uinavigation
#import "FWNavigationBar.h"
UINavigationController *controller = [UINavigationController initWithNavigationBarClass:[FWNavigationBar class] toolbarClass:nil];
[controller setViewControllers:@[rootViewController] animated:NO];
Création d'un UIBarButton
placez ce code soit dans une catégorie UIBarButton ou dans le fichier que vous prévoyez d'utiliser en utilisant le bouton Barre qui retournera un bouton de barre de recherche identique à l'aide d'un UIButton.
+ (UIBarButtonItem *)barButtonWithImage:(UIImage *)image target:(id)target action:(SEL)action {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
//Note: Only iOS 11 and up supports constraints on custom bar button views
button.frame = CGRectMake(0, 0, image.size.width, image.size.height);
button.tintColor = [UIColor lightGrayColor];//Adjust the highlight color
[button setImage:image forState:UIControlStateNormal];
//Tint color only applies to this image
[button setImage:[image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateHighlighted];
[button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
return [[UIBarButtonItem alloc] initWithCustomView:button];
}
mettre le bouton de la barre dans votre controller
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.leftBarButtonItem = [UIBarButtonItem barButtonWithImage:[UIImage imageNamed:@"your_button_image"] target:self action:@selector(leftButtonPressed)];
}
enfin, je recommande de laisser les marges Gauche et droite à zéro et de simplement ajuster la position du bouton dans votre image. Cela vous permettra de profiter de la pleine cliquable région jusqu'au bord de l'écran. Il en va de même pour la hauteur de votre image, assurez-vous que la hauteur est de 44 points.
j'ai remarqué un problème similaire.
je l'ai signalé une Pomme Radar pour un problème similaire, nous avons remarqué, #32674764 si vous souhaitez le consulter, si vous créez un Radar.
j'ai aussi créé un thread dans Apple forum, mais pas encore de feedback: https://forums.developer.apple.com/message/234654
je suis tombé sur ceci: UINavigationItem-Margin. Il fonctionne comme un charme.
Pris cette réponse: les BarButtons utilisent maintenant L'Autolayout et nécessitent donc des contraintes.
if #available(iOS 9.0, *) {
cButton.widthAnchor.constraint(equalToConstant: customViewButton.width).isActive = true
cButton.heightAnchor.constraint(equalToConstant: customViewButton.height).isActive = true
}
Objective-C
if (@available(iOS 9, *)) {
[cButton.widthAnchor constraintEqualToConstant: standardButtonSize.width].active = YES;
[cButton.heightAnchor constraintEqualToConstant: standardButtonSize.height].active = YES;
}
Solution 1: À la lumière de la réponse D'Apple que c'est Comportement attendu, nous avons travaillé autour du problème en supprimant la barre d'outils et en ajoutant une vue personnalisée.
je me rends compte que cela peut ne pas être possible dans tous les cas, mais L'uivi régulier est beaucoup plus facile à personnaliser à l'apparence de l'application que la barre d'outils et la barre de navigation où Apple a le contrôle du positionnement du bouton.
au lieu de définir notre bouton personnalisé comme la vue personnalisée de la barre d'interface utilisateur bouton de l'objet, il nous a été définie comme une sous-vue de la vierge de l'interface utilisateur boutons dans la vue personnalisée.
Solution 2: Un peu désordonné, nous avons enveloppé notre bouton de vue personnalisé dans un UIButton externe afin que l'emplacement du cadre peut être réglé. Cela rend le bord gauche externe du bouton Non-tappable malheureusement, mais corrige l'apparence de la position du bouton. Voir l'exemple:
UIButton* outerButton = [UIButton new]; //the wrapper button
BorderedButton* button = [self initBorderedButton]; //the custom button
[button setTitle:label forState:UIControlStateNormal];
[button setFrame:CGRectMake(-10, 0, [label length] * 4 + 35, 30)];
[button addTarget:controller action:@selector(popCurrentViewController) forControlEvents:UIControlEventTouchUpInside];
[outerButton addSubview:button]; //add custom button to outer wrapper button
[outerButton setFrameWidth:button.frameWidth]; //make sure title gives button appropriate space
controller.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:outerButton]; //add wrapper button to the navigation bar
controller.navigationItem.hidesBackButton = YES;