J'utilise une vue d'image pour afficher une image dans ma barre de navigation. Le problème est que je ne peux pas le régler correctement au centre à cause du bouton de retour. J'ai vérifié les questions connexes et j'ai eu presque le même problème que je l'avais résolu, mais cette fois, je n'en ai aucune idée.
Auparavant, j'avais résolu ce problème avec de faux boutons de barre, j'ai donc essayé d'ajouter un faux bouton de barre à droite (et à gauche), mais cela n'a pas aidé.
- (void) searchButtonNavBar {
CGRect imageSizeDummy = CGRectMake(0, 0, 25,25);
UIButton *dummy = [[UIButton alloc] initWithFrame:imageSizeDummy];
UIBarButtonItem
*searchBarButtonDummy =[[UIBarButtonItem alloc] initWithCustomView:dummy];
self.navigationItem.rightBarButtonItem = searchBarButtonDummy;
}
- (void)setNavBarLogo {
[self setNeedsStatusBarAppearanceUpdate];
CGRect myImageS = CGRectMake(0, 0, 44, 44);
UIImageView *logo = [[UIImageView alloc] initWithFrame:myImageS];
[logo setImage:[UIImage imageNamed:@"color.png"]];
logo.contentMode = UIViewContentModeScaleAspectFit;
self.navigationItem.titleView = logo;
[[UIBarButtonItem appearance] setTitlePositionAdjustment:UIOffsetMake(0.0f, 0.0f) forBarMetrics:UIBarMetricsDefault];
}
Je pense que cela devrait fonctionner car dans ce cas, la titleView
a des boutons de barres du même côté. Y a-t-il une explication à la raison pour laquelle cela a fonctionné avec les boutons de barre créés par programme mais ne fonctionne pas avec le bouton retour commun?
UINavigationBar
centre automatiquement sa titleView
tant qu'il y a suffisamment de place. Si le titre n'est pas centré, cela signifie que la vue du titre est trop large pour être centré et si vous définissez backgroundColor si votre UIImageView
vous verrez que c'est exactement ce qui se passe.
La vue du titre est trop large car cette barre de navigation redimensionnera automatiquement le titre pour contenir son contenu, à l'aide de -sizeThatFits:
. Cela signifie que la vue de votre titre sera toujours redimensionnée à la taille de votre image.
Deux solutions possibles:
L'image que vous utilisez est trop grande. Utilisez une image de 44 x 44 pt de taille appropriée avec les versions 2x et 3x.
Enveloppez UIImageView dans un UIView normal pour éviter le redimensionnement.
Exemple:
UIImageView* imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"test.jpeg"]];
imageView.contentMode = UIViewContentModeScaleAspectFit;
UIView* titleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
imageView.frame = titleView.bounds;
[titleView addSubview:imageView];
self.navigationItem.titleView = titleView;
Un exemple dans Swift 3 version du second moyen de Darren:
let imageView = UIImageView(image: UIImage(named: "test"))
imageView.contentMode = UIViewContentMode.scaleAspectFit
let titleView = UIView(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
imageView.frame = titleView.bounds
titleView.addSubview(imageView)
self.navigationItem.titleView = titleView
Je vous suggère de remplacer la fonction - (void) setFrame: (CGRect) fram Comme ceci:
- (void)setFrame:(CGRect)frame {
[super setFrame:frame]; //systom function
self.center = CGPointMake(self.superview.center.x, self.center.y); //rewrite function
}
afin que le titleView.center toujours au bon endroit
N'utilisez pas titleView.
Ajoutez simplement votre image à navigationController.navigationBar
CGRect myImageS = CGRectMake(0, 0, 44, 44);
UIImageView *logo = [[UIImageView alloc] initWithFrame:myImageS];
[logo setImage:[UIImage imageNamed:@"color.png"]];
logo.contentMode = UIViewContentModeScaleAspectFit;
logo.center = CGPointMake(self.navigationController.navigationBar.width / 2.0, self.navigationController.navigationBar.height / 2.0);
logo.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
[self.navigationController.navigationBar addSubview:logo];
Qun Li a parfaitement fonctionné pour moi. Voici le code Swift 2.3:
override var frame: CGRect {
set(newValue) {
super.frame = newValue
if let superview = self.superview {
self.center = CGPoint(x: superview.center.x, y: self.center.y)
}
}
get {
return super.frame
}
}
Si vous utilisez une vue personnalisée depuis un nib, veillez à désactiver la mise en page automatique sur le fichier nib.
J'ai créé une variable UINavigationController
personnalisée qui, après être passé, n'a plus qu'à appeler showNavBarTitle(title:font:)
lorsque vous souhaitez afficher et removeNavBarTitle()
lorsque vous souhaitez masquer:
class NavigationController: UINavigationController {
private static var mTitleFont = UIFont(name: <your desired font (String)> , size: <your desired font size -- however, font size will automatically adjust so the text fits in the label>)!
private static var mNavBarLabel: UILabel = {
let x: CGFloat = 60
let y: CGFloat = 7
let label = UILabel(frame: CGRect(x: x, y: y, width: UIScreen.main.bounds.size.width - 2 * x, height: 44 - 2 * y))
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.5
label.font = NavigationController.mTitleFont
label.numberOfLines = 0
label.textAlignment = .center
return label
}()
func showNavBarLabel(title: String, font: UIFont = mTitleFont) {
NavigationController.mNavBarLabel.text = title
NavigationController.mNavBarLabel.font = font
navigationBar.addSubview(NavigationController.mNavBarLabel)
}
func removeNavBarLabel() {
NavigationController.mNavBarLabel.removeFromSuperview()
}
}
Je trouve que le meilleur endroit pour appeler showNavBarTitle(title:font:)
et removeNavBarTitle()
se trouvent dans les méthodes viewWillAppear()
et viewWillDisappear()
du contrôleur de vue, respectivement:
class YourViewController: UIViewController {
func viewWillAppear() {
(navigationController as! NavigationController).showNavBarLabel(title: "Your Title")
}
func viewWillDisappear() {
(navigationController as! NavigationController).removeNavBarLabel()
}
}
1) Vous pouvez essayer de définir votre image comme image d’arrière-plan de UINavigationBar en appelant
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"color.png"] forBarMetrics:UIBarMetricsDefault];
dans la méthode viewDidLoad
.
De cette façon, il sera toujours centré, mais si vous avez le bouton back
avec un titre long comme élément de navigation de gauche, il peut apparaître au-dessus de votre logo. Et vous devriez probablement au début créer une autre image avec la même taille que la barre de navigation, puis dessinez votre image en son centre, puis définissez-la comme image d'arrière-plan.
2) Ou au lieu de définir votre vue d'image sur titleView
, vous pouvez simplement ajouter l'ajout en tant que sous-vue afin d'éviter les contraintes liées aux éléments des boutons des barres de droite et de gauche.
Dans Swift, c’est ce qui a fonctionné pour moi, mais ce n’est pas la meilleure solution (en gros, ajoutez-la à navigationBar):
let titleIV = UIImageView(image: UIImage(named:"some"))
titleIV.contentMode = .scaleAspectFit
titleIV.translatesAutoresizingMaskIntoConstraints = false
if let navigationController = self.navigationController{
navigationController.navigationBar.addSubview(titleIV)
titleIV.centerXAnchor.constraint(equalTo:
navigationController.navigationBar.centerXAnchor).isActive = true
titleIV.centerYAnchor.constraint(equalTo: navigationController.navigationBar.centerYAnchor).isActive = true
}
else{
view.addSubview(titleIV)
titleIV.topAnchor.constraint(equalTo: view.topAnchor, constant: UIApplication.shared.statusBarFrame.height).isActive = true
titleIV.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}
Pour prolonger la réponse de Darren, un correctif pour moi était de retourner une sizeThatFits
avec la taille UILabel
. Il s'avère que cela s'appelle après layoutSubViews afin que l'étiquette ait une taille.
override func sizeThatFits(_ size: CGSize) -> CGSize {
return CGSize(width: titleLabel.frame.width + titleInset*2, height: titleLabel.frame.height)
}
Notez aussi que j'ai + titleInset*2
parce que je règle les contraintes horizontales comme ceci:
titleLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: titleInset),
titleLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -titleInset)