J'ai une barre de navigation avec les deux boutons de barre gauche et droite de chaque côté. J'ai une customTitlelabel
que j'ai définie comme titleView de la UINavigationItem
.
[self.navigationItem setTitleView: customTitleLabel];
Tout va bien maintenant. Le problème, la taille du rightbarButton est dynamique en fonction de l'entrée que je reçois dans l'un des champs de texte.
Par conséquent, le titre est automatiquement centré en fonction de l'espace disponible entre les boutons.
comment puis-je définir le titre à une position fixe?
Vous ne pouvez pas faire ce que vous voulez directement - la position de votre vue du titre est hors de votre contrôle (lorsqu'elle est gérée par UINavigationBar
).
Cependant, il existe au moins deux stratégies pour obtenir l'effet souhaité:
1) Ajoutez la vue du titre non pas en tant que vue du titre 'approprié' de la barre de navigation, mais en tant que sous-vue de la UINavigationBar
. (Remarque: ceci n'est pas "officiellement" sanctionné, mais je l'ai déjà vu et fonctionne. Évidemment, vous devez surveiller votre étiquette de titre en écrasant des morceaux de boutons, et gérer des barres de navigation de différentes tailles pour différentes orientations, etc. - un peu délicat.)
2) Créez une sous-classe intelligente UIView qui affiche une sous-vue donnée (qui serait votre UILabel) à une position calculée pour afficher efficacement la sous-vue parfaitement centrée sur l'écran. Pour ce faire, votre sous-classe intelligente UIView répondrait aux événements de présentation (ou aux modifications de la propriété frame
, etc.) en modifiant la position (frame
) de la sous-vue de l'étiquette.
Personnellement, j'aime bien l'idée d'approche 2) la meilleure.
La définition de la propriété titleView de la barre de navigation fonctionne parfaitement - il n'est pas nécessaire de sous-classer ou de modifier des cadres autres que ceux de votre vue personnalisée.
L'astuce pour le centrer par rapport à la largeur totale de UINavigationBar consiste à:
Voici un exemple de code qui crée un titleView personnalisé avec une étiquette qui reste centrée dans UINavigationBar indépendamment de l’orientation, de la largeur du bouton à gauche ou à droite:
self.title = @"My Centered Nav Title";
// Init views with rects with height and y pos
CGFloat titleHeight = self.navigationController.navigationBar.frame.size.height;
UIView *titleView = [[UIView alloc] initWithFrame:CGRectZero];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
// Set font for sizing width
titleLabel.font = [UIFont boldSystemFontOfSize:20.f];
// Set the width of the views according to the text size
CGFloat desiredWidth = [self.title sizeWithFont:titleLabel.font
constrainedToSize:CGSizeMake([[UIScreen mainScreen] applicationFrame].size.width, titleLabel.frame.size.height)
lineBreakMode:UILineBreakModeCharacterWrap].width;
CGRect frame;
frame = titleLabel.frame;
frame.size.height = titleHeight;
frame.size.width = desiredWidth;
titleLabel.frame = frame;
frame = titleView.frame;
frame.size.height = titleHeight;
frame.size.width = desiredWidth;
titleView.frame = frame;
// Ensure text is on one line, centered and truncates if the bounds are restricted
titleLabel.numberOfLines = 1;
titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
titleLabel.textAlignment = NSTextAlignmentCenter;
// Use autoresizing to restrict the bounds to the area that the titleview allows
titleView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
titleView.autoresizesSubviews = YES;
titleLabel.autoresizingMask = titleView.autoresizingMask;
// Set the text
titleLabel.text = self.title;
// Add as the nav bar's titleview
[titleView addSubview:titleLabel];
self.navigationItem.titleView = titleView;
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.topItem?.title = ""
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
navigationItem.title = "Make peace soon"
}
La bonne réponse consiste à remplacer le sizeThatFits:
de votre titleView
personnalisée et à lui renvoyer la taille du contenu. La barre de navigation centre la vue des titres personnalisés jusqu'à ce qu'il ne reste plus d'espace pour le faire.
Par exemple, si vous avez un conteneur UIView
avec UILabel
à l'intérieur:
@interface CustomTitleView : UIView
@property UILabel* textLabel;
@end
@implementation CustomTitleView
- (CGSize)sizeThatFits:(CGSize)size {
CGSize textSize = [self.textLabel sizeThatFits:size];
CGSize contentSize = size;
contentSize.width = MIN( size.width, textSize.width );
return contentSize;
}
@end
J'ai essayé la réponse de aopsfan mais cela n'a pas fonctionné. Un point d'arrêt a révélé que le centre de la barre était "(480.0, 22.0)" (la coordonnée X est complètement éteinte).
Alors je l'ai changé en ceci:
- (void)layoutSubviews
{
[super layoutSubviews];
// Center Title View
UINavigationItem* item = [self topItem]; // (Current navigation item)
[item.titleView setCenter:CGPointMake(160.0, 22.0)];
// (...Hard-coded; Assuming portrait iPhone/iPod touch)
}
... et ça marche comme un charme. L'effet de glissement/fondu lorsque vous appuyez sur les contrôleurs de vue est intact. (iOS 5.0)
J'ai eu le même problème. Ma solution est de masquer le bouton Précédent, puis d'ajouter votre propre implémentation. Puisque le système réservera de l'espace pour les éléments de gauche.
UIImage* cancelIcon = [UIImage imageNamed:@"ic_clear"];
UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc] initWithImage:cancelIcon style:UIBarButtonItemStylePlain target:self action:@selector(back:)];
et le sélecteur est simple
- (void)back:(UIButton *) sender
{
[self.navigationController popViewControllerAnimated:YES];
}
maintenant cela ressemble à ceci:
oh ... et n'oubliez pas d'utiliser autolayout dans votre vue de titre personnalisée si vous avez un contenu de longueur dynamique comme label. J'ajoute une mise en page supplémentaire dans la vue personnalisée pour lui donner le style "wrap_content" dans Android en le définissant centré sur parent, ainsi que l'espace de début et fin "> =" 0
J'ai eu une situation similaire où une titleView
devrait être centré dans UINavigationBar. J'aime l'approche d'occulus consistant à sous-classer un UIView et à surcharger setFrame:
. Ensuite, je peux centrer le cadre dans les dimensions de UINavigationBar.
Dans la sous-classe UIView:
-(void)setFrame:(CGRect)frame{
super.frame = CGRectMake(320 / 2 - 50, 44 / 2 - 15, 100, 30);
}
La sous-classe UIView peut ensuite être affectée normalement à titleView
pour chaque élément de navigation. Le développeur n'a pas besoin d'ajouter et de supprimer par programme des sous-vues spéciales de UINavigationBar.