Programmgesteuert die Höhe der Navigationsleiste abrufen


131

Ich weiß, dass das Vorhandensein des mehr Ansichts-Controllers (Navigationsleiste) das UIView um seine Höhe nach unten drückt. Ich weiß auch, dass diese Höhe = 44px ist. Ich habe auch festgestellt, dass dieser Druck nach unten die [self.view].frame.origin.y = 0.

Wie bestimme ich die Höhe dieser Navigationsleiste, anstatt sie nur auf eine Konstante zu setzen?

Oder, kürzere Version, wie stelle ich fest, dass mein UIView mit der Navigationsleiste oben angezeigt wird?


Die Glühbirne ging an. Leider habe ich keinen einheitlichen Weg gefunden, um das Problem zu beheben, wie unten beschrieben.

Ich glaube, dass sich mein gesamtes Problem auf meine Autoresizing-Masken konzentriert. Und der Grund, warum ich zu dem Schluss gekommen bin, dass es dieselben Symptome gibt, mit oder ohne UIWebView. Und dieses Symptom ist, dass für Portrait alles pfirsichfarben ist. Bei Querformat wird der unterste UIButton hinter der TabBar angezeigt.

Zum Beispiel habe ich in einem UIView von oben nach unten:

UIView - beide Federn eingestellt (Standardfall) und keine Streben

UIScrollView - Wenn ich die beiden Federn setze und alles andere lösche (wie das UIView), dringt der UIButton in das Objekt unmittelbar darüber ein. Wenn ich alles lösche, ist UIButton in Ordnung, aber das Material ganz oben versteckt sich hinter der Statusleiste. Wenn Sie nur die obere Strebe einstellen, wird der UIButton hinter der Tab-Leiste angezeigt.

UILabel und UIImage als nächstes vertikal - oberes Strebenset, überall flexibel

Nur um das Bild für die wenigen zu vervollständigen, die eine UIWebView haben:

UIWebView - Streben: oben, links, rechts Federn: beide

UIButton - nichts festgelegt, dh überall flexibel

Obwohl meine Glühbirne schwach ist, scheint es Hoffnung zu geben.


Bitte nehmen Sie mit, weil ich mehr Platz brauchte, als für einen kurzen Antwortkommentar vorgesehen war.

Vielen Dank, dass Sie versucht haben zu verstehen, wonach ich wirklich fische.

1) Jeder UIViewController (eine TabBar-App) verfügt über ein UIImage, Text und was auch immer. Ein weiterer gemeinsamer Nenner ist ein UIButton auf der Unterseite. Auf einigen UIViewControllern habe ich eine UIWebView über dem UIButton.

Also, UIImage, Text usw. UIWebView (auf EINIGEN) UIButton

Um all das oben Genannte ist eine UIScrollView.

2) Für diejenigen, die eine UIWebView haben, sieht die AutoresizingMask wie folgt aus:

   
   |
   

   ^
   |
   |

| - | ← ---- → | - | | | V Die Maske des UIButton ist nicht festgelegt, dh überall flexibel

In meinem -viewDidLoad rufe ich meine -repositionSubViews auf, in denen ich Folgendes mache:

Wenn es keine UIWebView gibt, mache ich nichts anderes als den UIButton zu zentrieren, den ich mit IB platziert habe.

Wenn ich eine UIWebView habe, bestimme ich deren * Inhalt * -Höhe und setze ihren Rahmen so, dass er den gesamten Inhalt einschließt.

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

Sobald ich das mache, drücke ich den UIButton programmgesteuert nach unten, so dass er unter der UIWebView platziert wird.

Alles funktioniert, bis ich es von Porträt zu Landschaft drehe.

Ich rufe meine -repositionSubViews in meiner -didRotateFromInterfaceOrientation auf.

Warum ändert sich die Inhaltshöhe meines UIWebView nicht mit der Drehung?

Von Hochformat zu Querformat sollte die Inhaltsbreite erweitert und die Inhaltshöhe verringert werden. Es funktioniert optisch so, wie es sollte, aber nicht gemäß meinem NSLog.

Wie auch immer, mit oder ohne UIWebView bewegt sich die Schaltfläche, über die ich gesprochen habe, im Querformat unter die TabBar, aber sie wird nicht nach oben gescrollt, um gesehen zu werden. Ich sehe es hinter der TabBar, wenn ich "kräftig" scrolle, aber dann "fällt" es hinter der TabBar zurück.

Unterm Strich ist dies der letzte Grund, warum ich nach der Höhe der TabBar und der Navigationsleiste gefragt habe, da sich die TabBar am unteren Rand der UIView befindet und die Navigationsleiste die UIView nach unten drückt.

Jetzt werde ich hier ein oder zwei Kommentare hinzufügen, weil sie früher keinen Sinn ergeben hätten.

Ohne UIWebView lasse ich alles so, wie es von IB gesehen wird.

Mit einer UIWebView erhöhe ich die Frame.Höhe der UIWebView auf ihre Inhaltshöhe und passe auch die Höhe der umgebenden UIScrollView, die alle Unteransichten umgibt, nach oben an.

Na da hast du es.

Antworten:


258

So etwas machen?

    NSLog(@"Navframe Height=%f",
        self.navigationController.navigationBar.frame.size.height);

Die schnelle Version befindet sich hier


AKTUALISIEREN

iOS 13

Da das statusBarFramein veraltet war iOS13, können Sie dies verwenden:

extension UIViewController {

    /**
     *  Height of status bar + navigation bar (if navigation bar exist)
     */

    var topbarHeight: CGFloat {
        return (view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0.0) +
            (self.navigationController?.navigationBar.frame.height ?? 0.0)
    }
}

Danke Danke. ABER, jetzt, da Sie dieses Problem gelöst haben, wie kann ich feststellen, ob der NavigationController, auch bekannt als MoreViewController, für meine Registerkarten-App angezeigt wird?

Ich verstehe nicht ganz, was Sie sagen wollen. Versuchen Sie herauszufinden, ob MoreViewController angezeigt wird? (Wenn ja, was möchten Sie tun?) Und wenn nicht, können Sie klarstellen, was genau Sie meinen?
Summe

Ich habe Ihre Frage noch einmal gelesen und immer noch nicht verstanden, was Sie tun möchten? Wenn Sie etwas tun möchten, wenn die Ansicht angezeigt wird, sollten Sie den Code in viewDidAppear einfügen. Wenn Sie ein wenig klarstellen, wird es einfacher, herauszufinden, was Sie tun möchten.
Summe

2
Ich weiß, dass dies nicht die Frage anspricht, die er gestellt hat, aber anscheinend wollte er sehen, ob die Navigationsleiste versteckt war oder nicht. Wenn ja, hätte er self.navigationController.navigationBarHidden Hope voll nutzen können, dies hilft jemandem :)
Taylorcressy

2
In iOS 7+ müssen Sie möglicherweise auch die 20px-Statusleiste berücksichtigen, abhängig von Ihrer Anwendung
Slayter

94

Mit dem iPhone-X wird die Höhe der oberen Leiste (Navigationsleiste + Statusleiste) geändert (erhöht).

Versuchen Sie dies, wenn Sie die genaue Höhe der oberen Leiste (sowohl Navigationsleiste als auch Statusleiste) wünschen:

AKTUALISIEREN

iOS 13

Da das statusBarFramein veraltet war iOS13, können Sie dies verwenden:

extension UIViewController {

    /**
     *  Height of status bar + navigation bar (if navigation bar exist)
     */

    var topbarHeight: CGFloat {
        return (view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0.0) +
            (self.navigationController?.navigationBar.frame.height ?? 0.0)
    }
}

Ziel c

CGFloat topbarHeight = ([UIApplication sharedApplication].statusBarFrame.size.height +
       (self.navigationController.navigationBar.frame.size.height ?: 0.0));

Swift 4

let topBarHeight = UIApplication.shared.statusBarFrame.size.height +
        (self.navigationController?.navigationBar.frame.height ?? 0.0)

Probieren Sie diese UIViewController-Erweiterung aus

extension UIViewController {

    /**
     *  Height of status bar + navigation bar (if navigation bar exist)
     */

    var topbarHeight: CGFloat {
        return UIApplication.shared.statusBarFrame.size.height +
            (self.navigationController?.navigationBar.frame.height ?? 0.0)
    }
}

Swift 3

let topBarHeight = UIApplication.sharedApplication().statusBarFrame.size.height +
(self.navigationController?.navigationBar.frame.height ?? 0.0)


3
Die Swift 4-Antwort gibt für mich eine Höhe von 0 zurück.
Chewie The Chorkie

61

Schnelle Version:

let navigationBarHeight: CGFloat = self.navigationController!.navigationBar.frame.height

Gibt immer 44 zurück. Wie erkennt man die reduzierte Größe (44) oder die erweiterte Größe (große Titel)? Natürlich dynamisch. (Ich weiß, was es misst)
Markus

6

Hast du das versucht?

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

5

Unterstützt iOS 13 und niedriger:

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
        }
    }
}

4
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 );
*/

Alles was wir wirklich brauchen ist

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;

2

Meine Anwendung verfügt über einige Ansichten, für deren Erscheinungsbild eine angepasste Navigationsleiste in der Benutzeroberfläche erforderlich ist, jedoch ohne Navigationscontroller. Die Anwendung muss die iOS-Version vor iOS 11 unterstützen, sodass die praktische Anleitung für das Layout sicherer Bereiche nicht verwendet werden konnte und ich die Position und Höhe der Navigationsleiste programmgesteuert anpassen muss.

Ich habe die Navigationsleiste direkt an die Übersicht angehängt und die oben erwähnte Anleitung zum Layout des sicheren Bereichs übersprungen. Und die Höhe der Statusleiste könnte leicht aus UIApplication abgerufen werden, aber die Standardhöhe der Navigationsleiste ist wirklich ein Schmerz ...

Es fiel mir fast eine halbe Nacht lang auf, mit einer Reihe von Suchen und Tests, bis ich schließlich den Hinweis von einem anderen Beitrag bekam (der für mich allerdings nicht funktionierte), dass man tatsächlich die Höhe von UIView.sizeThatFits () wie diesem erhalten könnte ::

- (void)viewWillLayoutSubviews {
    self.topBarHeightConstraint.constant = [UIApplication sharedApplication].statusBarFrame.size.height;
    self.navBarHeightConstraint.constant = [self.navigationBar sizeThatFits:CGSizeZero].height;

    [super viewWillLayoutSubviews];    
}

Endlich eine perfekte Navigationsleiste, die genauso aussieht wie die eingebaute!


2

Wenn Sie navigationBarnur die Höhe erhalten möchten , ist es einfach:

extension UIViewController{
   var navigationBarHeight: CGFloat {
       return self.navigationController?.navigationBar.frame.height ?? 0.0
   }
}

Wenn Sie jedoch die Höhe der Spitzenklasse des iPhones benötigen, müssen Sie die navigationBarHöhe nicht ermitteln und die Höhe hinzufügen. statusBarSie können einfach anrufen safeAreaInsets, weshalb es sie gibt.

self.view.safeAreaInsets.top

1

Die Glühbirne ging an. Leider habe ich keinen einheitlichen Weg gefunden, um das Problem zu beheben, wie unten beschrieben.

Ich glaube, dass sich mein gesamtes Problem auf meine Autoresizing-Masken konzentriert. Und der Grund, warum ich zu dem Schluss gekommen bin, dass es dieselben Symptome gibt, mit oder ohne UIWebView. Und dieses Symptom ist, dass für Portrait alles pfirsichfarben ist. Bei Querformat wird der unterste UIButton hinter der TabBar angezeigt.

Zum Beispiel habe ich in einem UIView von oben nach unten:

UIView - beide Federn eingestellt (Standardfall) und keine Streben

UIScrollView - Wenn ich die beiden Federn setze und alles andere lösche (wie das UIView), dringt der UIButton in das Objekt unmittelbar darüber ein. Wenn ich alles lösche, ist UIButton in Ordnung, aber das Material ganz oben versteckt sich hinter der Statusleiste. Wenn Sie nur die obere Strebe einstellen, wird der UIButton hinter der Tab-Leiste angezeigt.

UILabel und UIImage als nächstes vertikal - oberes Strebenset, überall flexibel

Nur um das Bild für die wenigen zu vervollständigen, die eine UIWebView haben:

UIWebView - Streben: oben, links, rechts Federn: beide

UIButton - nichts festgelegt, dh überall flexibel

Obwohl meine Glühbirne schwach ist, scheint es Hoffnung zu geben.


Setze die obere Strebe und setze die beiden Federn des UIWebView - Problem gelöst und danke Bündel. Tatsächlich besteht mein einziges verbleibendes Problem darin, diese verfluchten @ 2X-Grafiken usw. zu entwerfen. Ich benutze GraphicConverter auf sehr einfache Weise und es eignet sich sehr gut für das Design von Webseiten. Aber all diese 30px, 57px Sachen - ich betrete zumindest für mich Neuland.

1

Hier ist der Beginn meiner Antwort auf Ihr Update:

Warum ändert sich die Inhaltshöhe meines UIWebView nicht mit der Drehung?

Könnte es sein, dass Ihre automatische Größenänderung nicht die automatische Größenmaske für alle Richtungen enthält?

Ein weiterer Vorschlag, bevor ich darauf zurückkomme, könnten Sie eine Symbolleiste für Ihre Bedürfnisse verwenden. Es ist etwas einfacher, wird immer unten sein, dreht sich automatisch / positioniert. Sie können es nach Belieben ausblenden / anzeigen usw. So ähnlich: http://cdn.artoftheiphone.com/wp-content/uploads/2009/01/yellow-pages-iphone-app-2.jpg

Sie haben sich diese Option vielleicht angesehen, sie aber einfach rausgeworfen.

Eine andere Idee, könnten Sie möglicherweise erkennen, aus welcher Ausrichtung Sie sich drehen, und die Schaltfläche einfach programmgesteuert platzieren, um sie an die Registerkartenleiste anzupassen. (Dies ist mit Code möglich)


Nach ungefähr zwei Wochen, in denen ich mich damit befasst hatte, entschied ich, dass das "Problem" durch Platzieren eines UIButton UNTER der UIWebView-Unteransicht erschwert wurde. Also habe ich den Knopf darüber gelegt. Ehrlich gesagt sieht es einfach nicht "richtig" aus ... aber es funktioniert jetzt SORT OF. UNTEN oder OBEN hat UIWebView die obere Strebe und nur die horizontale Feder eingestellt. Übrigens ist es die contentHeight der UIWebView, die sich mit der Rotation nicht ändert.

0

Ich habe benutzt:

let originY: CGFloat = self.navigationController!.navigationBar.frame.maxY

Funktioniert hervorragend, wenn Sie die Höhe der Navigationsleiste UND deren Y-Ursprung ermitteln möchten.


0

Swift 5

Wenn Sie auch die safeArea in Betracht ziehen möchten:

 let height = navigationController?.navigationBar.frame.maxY  

0

Praktische Swift 4-Erweiterung, falls sie für andere hilfreich ist. Funktioniert auch dann, wenn der aktuelle Ansichts-Controller keine Navigationsleiste anzeigt.

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
  }
}

Verwendung:

UINavigationController.navBarHeight()
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.