160 votes

Obtenir par programme la hauteur de la barre de navigation

Je sais que la présence du contrôleur more view (barre de navigation) fait descendre l'UIView de sa hauteur. Je sais aussi que cette hauteur = 44px. J'ai également découvert que cette poussée vers le bas maintient la valeur [self.view].frame.origin.y = 0 .

Comment puis-je déterminer la hauteur de cette barre de navigation, autrement qu'en lui attribuant une valeur constante ?

Ou, plus brièvement, comment puis-je déterminer que mon UIView s'affiche avec la barre de navigation en haut ?


L'ampoule a commencé à s'allumer. Malheureusement, je n'ai pas trouvé de moyen uniforme de corriger le problème, comme décrit ci-dessous.

Je crois que tout mon problème est lié à mes masques d'autoréglage. Et la raison pour laquelle j'en suis arrivé à cette conclusion est que les mêmes symptômes existent, avec ou sans UIWebView. Et ce symptôme est que tout est parfait pour le Portrait. Pour le Paysage, l'UIButton le plus bas se retrouve derrière la TabBar.

Par exemple, sur une vue UIV, j'ai, de haut en bas :

UIView - les deux ressorts sont réglés (cas par défaut) et il n'y a pas de jambes de force

UIScrollView - Si je place les deux ressorts et que j'efface tout le reste (comme l'UIView), alors l'UIButton empiète sur l'objet situé immédiatement au-dessus de lui. Si j'efface tout, l'UIButton est OK, mais l'objet situé tout en haut se cache derrière la StatusBar. En réglant uniquement l'étai supérieur, l'UIButton se retrouve derrière la Tab Bar.

UILabel et UIImage à la verticale - la jambe de force supérieure est fixée, elle est flexible partout ailleurs

Pour compléter l'image pour les quelques personnes qui ont un UIWebView :

UIWebView - Struts : top, left, right Springs : both

UIButton - rien de fixe, c'est-à-dire flexible partout

Bien que mon ampoule soit faible, il semble y avoir de l'espoir.


Soyez indulgents avec moi, car j'avais besoin de plus d'espace que celui prévu pour une brève réponse.

Merci d'avoir essayé de comprendre ce que je recherche vraiment ... alors voilà.

1) Chaque UIViewController (une application TabBar) contient une UIImage, du texte et d'autres éléments. Un autre dénominateur commun est un UIButton en bas. Sur certains des UIViewControllers, j'ai un UIWebView au-dessus de l'UIButton.

Ainsi, UIImage, texte, etc. UIWebView (sur SOME) UIButton

Tout cela est entouré d'une vue de défilement (UIScrollView).

2) Pour ceux qui ont un UIWebView, son autoresizingMask ressemble à :

   —
   |
   —

   ^
   |
   |

|-| ---- |-| | | V Le masque de l'UIButton n'est pas défini, c'est-à-dire qu'il est flexible partout.

Dans mon -viewDidLoad, j'appelle mon -repositionSubViews dans lequel je fais ce qui suit :

S'il n'y a pas de UIWebView, je ne fais rien d'autre que de centrer le bouton UIButton que j'ai placé avec IB.

Si j'ai un UIWebView, je détermine sa hauteur *contenu* et je définis son cadre pour qu'il englobe tout le contenu.

UIScrollView *scrollViewInsideWebView = [[webView_ subviews] lastObject];
webViewContentHeight = scrollViewInsideWebView.contentSize.height;
[webView_ setFrame:CGRectMake(webViewOriginX, webViewOriginY,
                          sameWholeViewScrollerWidth, webViewContentHeight)]

Une fois que j'ai fait cela, je pousse programmatiquement l'UIButton vers le bas de sorte qu'il se retrouve placé sous le UIWebView.

Tout fonctionne, jusqu'à ce que je le fasse pivoter de Portrait à Paysage.

J'appelle mes -repositionSubViews dans mon -didRotateFromInterfaceOrientation.

Pourquoi la hauteur du contenu de mon UIWebView ne change-t-elle pas avec la rotation ?

De Portrait à Paysage, la largeur du contenu doit s'étendre et la hauteur du contenu doit se réduire. Cela se passe visuellement comme il se doit, mais pas d'après mon NSLog.

Quoi qu'il en soit, avec ou sans UIWebView, le bouton dont j'ai parlé se déplace sous la TabBar en mode Paysage, mais il ne défile pas vers le haut pour être vu. Je le vois derrière la barre d'onglets lorsque je fais défiler "vigoureusement", mais il "retombe" ensuite derrière la barre d'onglets.

En fin de compte, c'est la raison pour laquelle j'ai posé des questions sur la hauteur de la TabBar et de la NavigationBar, car la TabBar se place au bas de l'UIView et la NavigationBar pousse l'UIView vers le bas.

Je vais maintenant ajouter un ou deux commentaires parce qu'ils n'auraient pas eu de sens tout à l'heure.

Sans UIWebView, je laisse tout tel quel, tel que vu par IB.

Dans le cas d'un UIWebView, j'augmente la hauteur du cadre de l'UIWebView jusqu'à sa hauteur de contenu et j'ajuste également à la hausse la hauteur de l'UIScrollView qui entoure toutes les sous-vues.

Voilà qui est fait.

12voto

Hitesh Surani Points 2175

Prise en charge d'iOS 13 et des versions inférieures :

extension UIViewController {

    var topbarHeight: CGFloat {
        if #available(iOS 13.0, *) {
            return (view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0.0) +
                (self.navigationController?.navigationBar.frame.height ?? 0.0)
        } else {
            let topBarHeight = UIApplication.shared.statusBarFrame.size.height +
            (self.navigationController?.navigationBar.frame.height ?? 0.0)
            return topBarHeight
        }
    }
}

8voto

Keaz Points 443

Avez-vous essayé cela ?

let barHeight = self.navigationController?.navigationBar.frame.height ?? 0

5voto

ironik sütlaç Points 61
UIImage*image = [UIImage imageNamed:@"logo"];

float targetHeight = self.navigationController.navigationBar.frame.size.height;
float logoRatio = image.size.width / image.size.height;
float targetWidth = targetHeight * logoRatio;

UIImageView*logoView = [[UIImageView alloc] initWithImage:image];
// X or Y position can not be manipulated because autolayout handles positions.
//[logoView setFrame:CGRectMake((self.navigationController.navigationBar.frame.size.width - targetWidth) / 2 , (self.navigationController.navigationBar.frame.size.height - targetHeight) / 2 , targetWidth, targetHeight)];
[logoView setFrame:CGRectMake(0, 0, targetWidth, targetHeight)];
self.navigationItem.titleView = logoView;

// How much you pull out the strings and struts, with autolayout, your image will fill the width on navigation bar. So setting only height and content mode is enough/
[logoView setContentMode:UIViewContentModeScaleAspectFit];

/* Autolayout constraints also can not be manipulated since navigation bar has  immutable constraints
self.navigationItem.titleView.translatesAutoresizingMaskIntoConstraints = false;

NSDictionary*metricsArray = @{@"width":[NSNumber numberWithFloat:targetWidth],@"height":[NSNumber numberWithFloat:targetHeight],@"margin":[NSNumber numberWithFloat:20]};
NSDictionary*viewsArray = @{@"titleView":self.navigationItem.titleView};

[self.navigationItem.titleView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>margin=)-H:[titleView(width)]-(>margin=)-|" options:NSLayoutFormatAlignAllCenterX metrics:metricsArray views:viewsArray]];
[self.navigationItem.titleView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[titleView(height)]" options:0 metrics:metricsArray views:viewsArray]];

NSLog(@"%f", self.navigationItem.titleView.width );
*/

Tout ce dont nous avons besoin, c'est donc

UIImage*image = [UIImage imageNamed:@"logo"];
UIImageView*logoView = [[UIImageView alloc] initWithImage:image];
float targetHeight = self.navigationController.navigationBar.frame.size.height;
[logoView setFrame:CGRectMake(0, 0, 0, targetHeight)];
[logoView setContentMode:UIViewContentModeScaleAspectFit];

self.navigationItem.titleView = logoView;

5voto

CodenameDuchess Points 806

Extension Swift 4 pratique, au cas où elle serait utile à quelqu'un d'autre. Fonctionne même si le contrôleur de vue actuel n'affiche pas de barre de navigation.

import UIKit

extension UINavigationController {
  static public func navBarHeight() -> CGFloat {
    let nVc = UINavigationController(rootViewController: UIViewController(nibName: nil, bundle: nil))
    let navBarHeight = nVc.navigationBar.frame.size.height
    return navBarHeight
  }
}

Utilisation :

UINavigationController.navBarHeight()

2voto

John Love Points 487

L'ampoule a commencé à s'allumer. Malheureusement, je n'ai pas trouvé de moyen uniforme de corriger le problème, comme décrit ci-dessous.

Je pense que tout mon problème est lié à mes masques d'autoréglage. Et la raison pour laquelle j'en suis arrivé à cette conclusion est que les mêmes symptômes existent, avec ou sans UIWebView. Et ce symptôme est que tout est parfait pour le Portrait. Pour le Paysage, l'UIButton le plus bas se retrouve derrière la TabBar.

Par exemple, sur une vue UIV, j'ai, de haut en bas :

UIView - les deux ressorts sont réglés (cas par défaut) et il n'y a pas de jambes de force

UIScrollView - Si je place les deux ressorts et que j'efface tout le reste (comme l'UIView), l'UIButton empiète sur l'objet situé immédiatement au-dessus de lui. Si j'efface tout, l'UIButton est OK, mais l'objet situé tout en haut se cache derrière la StatusBar. Si je ne règle que l'étai supérieur, l'UIButton se cache derrière la barre d'onglets.

UILabel et UIImage ensuite verticalement - jeu de jambes de force supérieur, flexible partout ailleurs

Pour compléter l'image pour les quelques personnes qui ont un UIWebView :

UIWebView - Amortisseurs : en haut, à gauche, à droite Ressorts : les deux

UIButton - rien de fixe, c'est-à-dire flexible partout

Bien que mon ampoule soit faible, il semble y avoir de l'espoir.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X