プログラムでナビゲーションバーの高さを取得する


131

moreビューコントローラー(ナビゲーションバー)の存在がUIViewの高さを押し下げることは知っています。この高さ= 44pxであることも知っています。このプッシュダウンがを維持していることも発見しました[self.view].frame.origin.y = 0

では、このナビゲーションバーの高さを、定数に設定するだけでなく、どのように決定するのでしょうか。

または、より短いバージョンでは、UIViewがナビゲーションバーを上にして表示されていることをどのように判断しますか?


電球が点灯し始めました。残念ながら、以下で説明するように、問題を修正するための統一された方法を発見していません。

私の問題はすべて私の自動サイズ変更マスクに集中していると思います。そして、UIWebViewの有無にかかわらず、同じ現象が存在すると私が結論付けた理由。そしてその症状は、ポートレートにとってすべてが桃色だということです。ランドスケープの場合、一番下のUIButtonがTabBarの後ろにポップアップします。

たとえば、私が持っている1つのUIViewで、上から下へ:

UIView –両方のスプリングが設定され(デフォルトの場合)、ストラットなし

UIScrollView-2つのスプリングを設定し、その他すべて(UIViewなど)をクリアすると、UIButtonはそのすぐ上のオブジェクトに侵入します。すべてをクリアすると、UIButtonは問題ありませんが、最上部にあるものはStatusBarの後ろに隠れます。上部のストラットのみを設定すると、UIButtonはタブバーの後ろにポップアップします。

次の垂直方向のUILabelとUIImage –トップストラットセット、他のあらゆる場所で柔軟

UIWebViewを持っている少数の人のために画像を完成させるためだけに:

UIWebView-Struts:上、左、右Springs:両方

UIButton –何も設定されていない、つまりどこでも柔軟

私の電球は暗いですが、希望があるようです。


短い返答コメントよりも多くのスペースが必要だったので、ご容赦ください。

私が実際に何のために釣りをしているのか理解してくれてありがとう...だからここに行く。

1)各UIViewController(TabBarアプリ)には、UIImage、いくつかのテキスト、その他の上に何でも持っています。別の共通点は、下部にあるUIButtonです。一部のUIViewControllersでは、UIButtonの上にUIWebViewがあります。

したがって、UIImage、テキストなど。UIWebView(一部の)UIButton

上記すべてを囲んでいるのがUIScrollViewです。

2)UIWebViewがあるものの場合、autoresizingMaskは次のようになります。

   
   |
   

   ^
   |
   |

| — | ←----→| — | | | V UIButtonのマスクには何も設定されていません。つまり、どこでも柔軟です

-viewDidLoad内で、-repositionSubViewsを呼び出し、その中で次のことを行います。

UIWebViewがない場合は、IBで配置したUIButtonを中央に配置する以外は何もしません。

UIWebViewがある場合は、その* content * Heightを決定して、コンテンツ全体を囲むようにフレームを設定します。

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

それを行ったら、プログラムでUIButtonを押し下げて、UIWebViewの下に配置されるようにします。

ポートレートからランドスケープに回転させるまで、すべてが機能します。

-didRotateFromInterfaceOrientation内で-repositionSubViewsを呼び出します。

UIWebViewのコンテンツの高さが回転しても変化しないのはなぜですか?

ポートレートからランドスケープまで、コンテンツの幅は拡大し、コンテンツの高さは縮小するはずです。視覚的には正常に機能しますが、NSLogによるとそうではありません。

とにかく、UIWebViewの有無にかかわらず、私が話したボタンはランドスケープモードではTabBarの下に移動しますが、上にスクロールして表示されません。「勢いよく」スクロールすると、TabBarの後ろに表示されますが、TabBarの後ろに「フォールバック」します。

つまり、TabBarはUIViewの下部に配置され、NavigationBarはUIViewを押し下げているためです。

ここでは、以前は意味がなかったので、ここにコメントを1つまたは2つ追加します。

UIWebViewがないので、IBで見られるようにすべてをそのままにします。

UIWebViewを使用して、UIWebViewのframe.heightをcontentHeightに増やし、すべてのサブビューを囲む周囲のUIScrollViewの高さを上方に調整します。

まあそこにあります。

回答:


258

このようなことをしますか?

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

迅速なバージョンはここにあります


更新

iOS 13

以下のようstatusBarFrameに廃止されましたiOS13あなたはこれを使用することができます:

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

ありがとうありがとう。しかし、その問題を解決したので、NavigationController(別名:MoreViewController)がタブバーアプリに表示されているかどうかをどのように判断すればよいでしょうか。

あなたの言っていることがよくわかりません。MoreViewControllerが表示されているかどうかを確認しようとしていますか?(もしそうなら、あなたは何をしたいですか?)そしてそうでなければ、あなたは正確にあなたが何を意味するのかを明確にできますか?
2011

あなたの質問をもう一度読みましたが、それでもあなたが何をしたいのか理解できませんでしたか?ビューが表示されたときに何かを実行する場合は、viewDidAppearにコードを挿入する必要があります。少し明確にすれば、やりたいことがわかりやすくなります。
合計

2
私はこれが彼が尋ねた質問に対処していないことを知っていますが、それは彼がnavigationBarが隠されているかどうかを確認しようとしていたようです。もしそうなら、彼はself.navigationController.navigationBarHiddenを使用することができたでしょうこれは誰かを完全に助けます:)
taylorcressy

2
iOS 7以降では、アプリケーションによっては20pxのステータスバーも考慮する必要があるかもしれません
Slayter

94

iPhone-Xでは、トップバー(ナビゲーションバー+ステータスバー)の高さが変更(増加)されています。

トップバー(ナビゲーションバー+ステータスバーの両方)の正確な高さが必要な場合は、これを試してください:

更新

iOS 13

以下のようstatusBarFrameに廃止されましたiOS13あなたはこれを使用することができます:

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

Objective-C

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

スウィフト4

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

簡単にするために、このUIViewController拡張機能を試してください

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

スウィフト3

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


3
Swift 4の回答では、身長0が返されます。
Chewie The Chorkie

61

Swiftバージョン:

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

常に44を返します。折りたたみサイズ(44)またはエキスパンドサイズ(大きいタイトル)を知る方法は??? もちろん、動的に。(私はそれが何を測定するか知っています)
Markus

6

やってみましたか?

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

5

iOS 13以前をサポート:

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

したがって、実際に必要なのは

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

私のアプリケーションには、ルックアンドフィールのためにUIにカスタマイズされたナビゲーションバーを必要とするいくつかのビューがありますが、ナビゲーションコントローラーがありません。また、アプリケーションはiOS 11より前のiOSバージョンをサポートする必要があるため、便利なセーフエリアレイアウトガイドを使用できず、ナビゲーションバーの位置と高さをプログラムで調整する必要があります。

ナビゲーションバーを直接スーパービューに接続し、上記のセーフエリアレイアウトガイドをスキップしました。ステータスバーの高さはUIApplicationから簡単に取得できますが、デフォルトのナビゲーションバーの高さは本当に面倒です...

次のように、UIView.sizeThatFits()から実際に高さを取得できるというヒントが別の投稿から(私には機能しません)ついに届くまで、検索とテストを何度も行い、ほぼ半夜にわたって私を襲いました。 :

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

    [super viewWillLayoutSubviews];    
}

最後に、組み込みのナビゲーションバーとまったく同じに見える完璧なナビゲーションバーです。


2

navigationBar高さのみを取得したい場合、それは簡単です:

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

ただし、iPhoneの最上部の高さが必要な場合は、高さを取得してnavigationBar高さを追加する必要はありません。これが存在する理由であるstatusBarと簡単に言えますsafeAreaInsets

self.view.safeAreaInsets.top

1

電球が点灯し始めました。残念ながら、以下で説明するように、問題を修正するための統一された方法を発見していません。

私の問題はすべて私の自動サイズ変更マスクに集中していると思います。そして、UIWebViewの有無にかかわらず、同じ現象が存在すると私が結論付けた理由。そしてその症状は、ポートレートにとってすべてが桃色だということです。ランドスケープの場合、一番下のUIButtonがTabBarの後ろにポップアップします。

たとえば、私が持っている1つのUIViewで、上から下へ:

UIView –両方のスプリングが設定され(デフォルトの場合)、ストラットなし

UIScrollView -2つのスプリングを設定し、その他すべて(UIViewなど)をクリアすると、UIButtonはそのすぐ上のオブジェクトに侵入します。すべてをクリアすると、UIButtonは問題ありませんが、最上部にあるものはStatusBarの後ろに隠れます。上部のストラットのみを設定すると、UIButtonはタブバーの後ろにポップアップします。

次の垂直方向のUILabelとUIImage –トップストラットセット、他のあらゆる場所で柔軟

UIWebViewを持っている少数の人のために画像を完成させるためだけに:

UIWebView -Struts:上、左、右Springs:両方

UIButton –何も設定されていない、つまりどこでも柔軟

私の電球は暗いですが、希望があるようです。


トップストラットを設定し、UIWebViewの2つのスプリングを設定します。問題は解決され、ありがとうございました。実際のところ、私の唯一の問題は、これらの呪われた@ 2Xなどのグラフィックをデザインすることです。私は非常にシンプルな方法でGraphicConverterを使用しており、Webページのデザインには非常に適しています。しかし、これらすべての30px、57pxのもの-少なくとも私にとっては、チャーターされていない領域に入ります。

1

ここにあなたの更新に対する私の応答の始まりがあります:

UIWebViewのコンテンツの高さが回転しても変化しないのはなぜですか?

それはあなたの自動サイズ変更がすべての方向のためのautoresizingMaskを持っていないためでしょうか?

これに戻る前のもう1つの提案として、ニーズに応じてツールバーを使用できますか。それは少し簡単です、常に一番下にあります、自動回転/位置。あなたは自由にそれを隠したり表示したりすることができます。このようなもの:http : //cdn.artoftheiphone.com/wp-content/uploads/2009/01/yellow-pages-iphone-app-2.jpg

あなたはそのオプションを見たかもしれませんが、そこに捨てるだけです。

別のアイデアとして、どの方向から回転しているかを検出し、ボタンをプログラムで配置してタブバーを調整することもできます。(これはコードで可能です)


これに取り組んだ約2週間後、UIWebViewサブビューの下にUIButtonを配置することにより、「問題」がより困難になると判断しました。だから、私はそれの上にボタンを置きます。率直に言って、それはそのように「正しく」見えないだけです...しかし、今ではSORT OFで動作します。UIWebViewの下または上は、上部支柱と水平スプリングのみを設定しています。ところで、回転しても変化しないUIWebViewのcontentHeightです。

0

利用した:

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

ナビゲーションバーの高さとそのY原点を取得する場合は、非常に効果的です。



0

他の人に役立つ場合に備えて、Handy Swift 4拡張機能。現在のビューコントローラーにナビゲーションバーが表示されない場合でも機能します。

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

使用法:

UINavigationController.navBarHeight()
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.