ステータスバーとナビゲーションバーがiOS 7のビューの境界の上に表示される


435

最近、Xcode 5 DPをダウンロードしてiOS 7でアプリをテストしました。最初に気づき、確認したのは、ステータスバーとナビゲーションバーに合わせてビューの境界が常にサイズ変更されるわけではないということです。

ではviewDidLayoutSubviews、ビューの境界を印刷します。

{{0、0}、{320、568}}

これにより、コンテンツがナビゲーションバーとステータスバーの下に表示されます。

メイン画面の高さを取得し、ステータスバーの高さとナビゲーションバーの高さを差し引くことで、自分で高さを計算できることはわかっていますが、これは不要な余分な作業のようです。

この問題を解決するにはどうすればよいですか?

更新:

この特定の問題の解決策を見つけました。ナビゲーションバーの半透明プロパティをNOに設定します。

self.navigationController.navigationBar.translucent = NO;

これにより、ビューがナビゲーションバーとステータスバーの下にフレーム化されなくなります。

ただし、ナビゲーションバーを半透明にしたい場合の解決策は見つかりませんでした。たとえば、写真を全画面で表示する場合、ナビゲーションバーを半透明にして、その下にビューをフレームで囲みます。それは機能しますが、ナビゲーションバーの表示/非表示を切り替えると、さらに奇妙な結果が発生しました。最初のサブビュー(UIScrollView)は、境界yの原点を毎回変更します。


xcode 5 DPでも同じ問題が発生します
Gopesh Gupta 2013

解決策があるかどうか教えてください
Gopesh Gupta 2013

1
ナビゲーションバーで濃淡の色のプロパティを探します。その青色を好きなように変更できるはずです。
beebcon 2013

9
Appleがアプリに下位互換性を維持する機会を与えたことがないため、iOSのアップグレードは時々嫌いです。
Bagusflyer

3
問題がナビゲーションコントローラーのトップバーを非表示にした後のステータスバーの下にあるビューに関連している場合、@ Stunner stackoverflow.com/a/18976660/235206の回答をソリューションとして参照します
MiKL

回答:


495

これを実現するにはedgesForExtendedLayout、iOS7 SDKで呼び出される新しいプロパティを実装します。これを実現するには、次のコードを追加してください。

if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
        self.edgesForExtendedLayout = UIRectEdgeNone;

-(void)viewDidLoadメソッドに上記を追加する必要があります。

iOS 7では、UIのレイアウトと外観をカスタマイズする方法にいくつかの変更が加えられています。ビューコントローラーのレイアウト、ティントカラー、フォントの変更は、アプリ内のすべてのUIKitオブジェクトに影響します。さらに、ジェスチャレコグナイザAPIの機能強化により、ジェスチャ操作をより細かく制御できます。

ビューコントローラーの使用

iOS 7では、ビューコントローラーは全画面レイアウトを使用します。同時に、iOS 7では、ビューコントローラーがビューをレイアウトする方法をより詳細に制御できます。特に、フルスクリーンレイアウトの概念は、ビューコントローラーがビューの各エッジのレイアウトを指定できるように改良されました。

wantsFullScreenLayoutあなたが現在指定した場合、ビューコントローラのプロパティは、iOS 7で廃止されましたwantsFullScreenLayout = NO、それはiOSの7で実行したときに、ビューコントローラは、予期しない画面位置でそのコンテンツを表示することができます。

ビューコントローラーがビューをレイアウトする方法を調整するにUIViewController は、次のプロパティを提供します。

  • edgeForExtendedLayout

edgesForExtendedLayoutプロパティは使用UIRectEdgeなし、すべてを指定しないことに加えて、矩形の4辺のそれぞれを指定するタイプを、。edgesForExtendedLayoutバーの半透明性に関係なく、ビューのどのエッジを拡張するかを指定するために使用します。デフォルトでは、このプロパティの値はUIRectEdgeAllです。

  • extendedLayoutIncludesOpaqueBars

デザインで不透明なバーを使用する場合edgesForExtendedLayoutは、extendedLayoutIncludesOpaqueBarsプロパティ もNOに設定して調整します。(のデフォルト値extendedLayoutIncludesOpaqueBarsNOです。)

  • automaticallyAdjustsScrollViewInsets

スクロールビューのコンテンツインセットを自動的に調整しない場合は、NOに設定automaticallyAdjustsScrollViewInsetsします。(のデフォルト値はYESです。)automaticallyAdjustsScrollViewInsets

  • topLayoutGuide、bottomLayoutGuide

topLayoutGuide及びbottomLayoutGuide特性は、ビューコントローラのビューの上部または下部のバーのエッジの位置を示します。バーがビューの上部または下部に重なる場合、Interface Builderを使用topLayoutGuideして、bottomLayoutGuideの下部または上部に制約を作成することにより、バーを基準にビューを配置できます。(バーがビューに重ならない場合、の下部はビュー topLayoutGuideの上部と同じで、上部はビュー bottomLayoutGuideの下部と同じです。)要求されたときに両方のプロパティが遅延して作成されます。

参照してください、アップルドキュメント


2
iOS6ではコンパイルできません。それは、
performselector

8
はい、厥私はセレクタチェックが含まれている理由状態、もしあれば([自己respondsToSelector:@selector(edgesForExtendedLayout)])
Nandha

19
ナビゲーションバーがない場合、これは機能しません。その場合には、私の見解では、ステータスバー..後ろに延びている
ヴァン・ドゥ・トラン

4
@VanDuTranと同じ問題があります。ナビゲーションバーが非表示の場合、edgesForExtendedLayoutは役に立ちません。
2013

6
それは機能しますが、...半透明効果はもうありません...どのように半透明効果を維持することもできます...
Dipu Rajak

110

すべてをシフトダウンする距離を計算する必要はありません。このためのプロパティが組み込まれています。Interface Builderで、ビューコントローラーを強調表示して、属性インスペクターに移動します。ここで、「エッジの延長」という単語の横にチェックボックスがいくつか表示されます。ご覧のとおり、最初のスクリーンショットでは、デフォルトの選択ではコンテンツが上部バーと下部バーの下に表示されますが、不透明バーの下には表示されません。そのため、バースタイルを半透明に設定しないとうまくいきません。

最初のスクリーンショットを見るとわかるように、ナビゲーションバーの下に2つのUI要素が隠れています。(私はこれを説明するためにIBでワイヤーフレームを有効にしました)これらの要素、UIButtonおよびUISegmentedControlはどちらも「y」の原点がゼロに設定されており、ビューコントローラーは上部バーの下のコンテンツを許可するように設定されています。

ここに画像の説明を入力してください

この2番目のスクリーンショットは、[トップバーの下]チェックボックスをオフにするとどうなるかを示しています。ご覧のとおり、ビューコントローラビューは、y原点がナビゲーションバーの真下になるように適切に下に移動されています。

ここに画像の説明を入力してください

これは、を使用してプログラムで実行することもでき-[UIViewController edgesForExtendedLayout]ます。edgeForExtendedLayoutUIRectEdgeのクラスリファレンスへのリンクは次のとおりです

[self setEdgesForExtendedLayout:UIRectEdgeNone];

15
.xibのビューだけに同じことをするにはどうすればよいですか?
ボビックス2013

2
ビューにラベルを1つ追加し、指示に従いましたが、これは機能しません
RMRAHUL

5
@bobics XIBの質問に対する答えは、「できない」です。とにかくIB経由ではありません。レーダーを提出し、アップルが最終的にそれに対処することを願っています。
memmons 2013年

@ 0x7fffffffに感謝します。これは私が探していた情報であり、非常に役に立ちました。
カンポ

33

私は自分のビューをプログラムで作成し、これが私のために働いてしまいました:

- (void) viewDidLayoutSubviews {
    // only works for iOS 7+
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect viewBounds = self.view.bounds;
        CGFloat topBarOffset = self.topLayoutGuide.length;

        // snaps the view under the status bar (iOS 6 style)
        viewBounds.origin.y = topBarOffset * -1;

        // shrink the bounds of your view to compensate for the offset
        viewBounds.size.height = viewBounds.size.height + (topBarOffset * -1);
        self.view.bounds = viewBounds;
    }
}

ソースpg.39下部のtopLayoutGuideセクション)。


最後に、実際にこれのために働く答えを見つけました。よくできました!
StuartM 2013

1
ナビゲーションバーが非表示のときにビューコントローラのビューがステータスバーの下に表示されるという問題を解決するために、これはステータスバーの下にビューをスナップするコードです。
MiKL 2013年

注:これにより、画面の下部が見えなくなります。
2013年

1
また、iOS7 専用にビルドしない限り、上記のコードはエラーをスローしますtopLayoutGuide-iOS7のみです。
2013年

1
また、メインビューがUITableViewの場合、スクロールごとにviewDidLayoutSubviewsが呼び出されることに注意してください。UITableViewは、高さが15pxになるまで縮小されます。このコードを1回だけ実行するフラグを追加します。;)
Thomas Johannesmeyer

30

iOS 10以降のNIB / XIBファイルでも機能するSwift 3 / Swift 4ソリューション:

override func viewDidLoad() {
    super.viewDidLoad()

    edgesForExtendedLayout = []
}

これは私を助けてくれたものです…とてもシンプルです。おかげで:-)
Hernan Arber

本当に
助かり

これは10.x Swift 3+ IMOに最適なソリューションです
shokaveli

10

ビューに半透明のナビゲーションバーを表示したい場合(これは一種の見栄えです)、contentInsetなどを設定する必要があります。

ここに私がそれをする方法があります:

// Check if we are running on ios7
if([[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."][0] intValue] >= 7) {
      CGRect statusBarViewRect = [[UIApplication sharedApplication] statusBarFrame];
      float heightPadding = statusBarViewRect.size.height+self.navigationController.navigationBar.frame.size.height;

      myContentView.contentInset = UIEdgeInsetsMake(heightPadding, 0.0, 0.0, 0.0);
}

3
なぜそれを7.0と直接比較できないのですか
Leena

1
笑わかりました:マイナーが追加された特定のバージョンに対するチェックは、それほど堅牢ではありません。ただし、値がBIGGER以上であるかどうかを確認しているため、7.0と比較しても問題ありません;)
EeKay

1
@leena-これは7.x以降の機能です。バージョンが7以上かどうかを確認し、マイナーリビジョンをスキップします。
Magnus

2
タブバーの背後に表示されるtableViewの動作に問題がありました。これにより、テーブルの最後の行がタブバーの上にスクロールすることがなくなりました。myTableView.contentInset = UIEdgeInsetsMake(0、0.0、TabbarHeight、0)
James

contentInsetのプロパティですUIScrollView。メインビューがのサブクラスでない場合はどうなりますかUIScrollView。次に、オーバーラップの問題をどのように修正しますか?
Pwner 2013年

9

edgesForExtendedLayoutただし、iOS 7 SDKでアプリをビルドしてiOS 6にデプロイすると、ナビゲーションバーが半透明になり、ビューがその下に表示されます。したがって、iOS 7とiOS 6の両方で修正するには、次のようにします。

self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
    self.edgesForExtendedLayout = UIRectEdgeNone;   // iOS 7 specific

9

アプリのplistファイルに行を追加し、「コントローラーベースのステータスバーの外観を表示する」と呼び、NOに設定します。


7

最も簡単なトリックは、NIBファイルを開き、次の2つの簡単な手順を実行することです。

  1. それを切り替えて、好きなものに設定してください:

ここに画像の説明を入力してください

  1. 下に移動するUIView / UIIMageView / ...を選択します。私の場合、ロゴだけが重なっていたので、デルタを+15に設定しました。(またはステップ1でiOS 7を選択した場合は-15)

ここに画像の説明を入力してください

そして結果

前 後


6
機能しますが、これは維持するのが難しいソリューションのように見えます。パッチを当てるのではなく、単に問題を修正するのが最善です。
NLemay 2013

メインビューに適用すると機能しないため、すべてのビューのサブビューに対してプログラムで実行するのが最適です
wildmonkey

5

Swiftソリューション:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    self.edgesForExtendedLayout = UIRectEdge.None
}

4
これは現在、edgesForExtendedLayout = []
Leon

1
これは公開の回答なので、忘れずに電話してください:super.viewWillAppear(animated)
prodos

4

Stunnerの答えを拡張して、 if、それがiOS-7であるかどうかを確認ステートメントをテストすると、アプリがクラッシュするためです。

追加は追加されます:

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

したがって、このメソッドをMyViewControler.mファイルに追加することをお勧めします。

- (void) viewDidLayoutSubviews {
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect viewBounds = self.view.bounds;
        CGFloat topBarOffset = self.topLayoutGuide.length;
        viewBounds.origin.y = topBarOffset * -1;
        self.view.bounds = viewBounds;
    }
}

4

スウィフト3

override func viewWillAppear(_ animated: Bool) {
    self.edgesForExtendedLayout = []
}

3

Appleが作成したBannerViewControllerを使用して広告とBannerViewControllerに埋め込まれたScrollViewControllerを表示するシナリオがあります。

ナビゲーションバーがコンテンツを非表示にしないようにするには、2つの変更を行う必要がありました。

1)BannerViewController.mを変更します

- (void)viewDidLoad
{
   [super viewDidLoad];
   float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
   if (systemVersion >= 7.0) {
      self.edgesForExtendedLayout = UIRectEdgeNone;
   }
}

2)ScrollViewContollerを変更する

- (void)viewDidLoad
{
    [super viewDidLoad];
    float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (systemVersion >= 7.0) {
        self.edgesForExtendedLayout = UIRectEdgeBottom;
    }
}

これで、広告はナビゲーションバーで覆われるのではなく、ビューの下部に正しく表示され、上部のコンテンツが途切れません。


2

ビューに次のコードを設定するだけで表示されます。

  if ([[[UIDevice currentDevice] systemVersion] floatValue]<= 7) {
self.edgesForExtendedLayout = UIRectEdgeNone;
 }

これが私の状況でうまくいった唯一のものです。
goobliata


2

Swift 4.2-Xcode 10.0-iOS 12.0:

if #available(iOS 11.0, *) {} else {
  self.edgesForExtendedLayout = []
  self.navigationController?.view.backgroundColor = .white
}

1

私にとって、最も簡単な解決策は、2つのキーをplistに追加することです

ここに画像の説明を入力してください


+1、「ステータスバーが最初は非表示」= YESでしたが、「ビューコントローラベースのステータスバーの外観」= NOを追加すると、ステータスバーが表示されなくなりました。
JonasByström2013年

1

ドロップダウンリストから「View Controller-based status bar appear」というキーをの行として追加しますinfo.plist。このようなもの:

ここに画像の説明を入力してください


Interesting.itは私のcocos2dプロジェクトで役立ちました。このオプションを切り替えると、上部のステータスバーが完全に表示されなくなっていることがわかります。
Kursat Turkay 2013年

1

iPad(armv7、armv7s、amr64)によるアプリで同じ問題が発生しましたが、別のUIViewControllerを表示するだけで、ステータスバーの下にナビゲーションバーが表示されます...その解決策を見つけるのに多くの時間を費やしています。私はストーリーボードとUIBuilderのInterfaceBuilderを使用しているので、フルスクリーンからプレゼンテーションを設定すると、この問題が解決します。私のアプリではiPads => iOS8.0(iOS8.1でのテスト)でのみ機能し、iOS 7.1のiPadでは機能しません。スクリーンショットを見る


私の場合、私のメインビューは私のtabBarと重なっており、その理由はわかりませんでした。[エッジの延長]> [下のバーの下]がオンになっていることがわかります。アプリの背景が白で、tabBarの上にある程度の不透明度しか生成されなかったので、それを認識するのは本当に困難でした。ありがとう!
イエスロドリゲス

0

iOS 7でステータスバーを非表示にする手順:

1.アプリケーションのinfo.plistファイルに移動します。

2.そして、セット、ビューコントローラベースのステータスバーの外観:ブールNO

ステータスバーの問題が解決したと思います。


0

私の場合、loadView()が中断されました
このコードをました:self.edgesForExtendedLayout = UIRectEdgeNone

しかしloadView()を削除した後、すべてがうまくいきました

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