iOS7で自動的にAdjustsScrollViewInsets、extendedLayoutIncludesOpaqueBars、edgesForExtendedLayoutの違いを説明する


250

私はiOS7のUIの移行についてたくさん読んでいます。

私はどのようなこれらの3つのプロパティを取得することはできませんよautomaticallyAdjustsScrollViewInsetsextendedLayoutIncludesOpaqueBarsedgesForExtendedLayout

たとえば、ビューコントローラをステータスバーの下から開始しようとしていますが、達成できません。


5
そして、なぜ私はそれを読んでいないと思いますか?..問題は、私がそれをよく理解していないので、期待どおりに機能していないことです!! ..その理由
user1010819

1
ああ、私はあなたがそこで言っていたことを誤解しました。私はひいきにするつもりはありませんでした。これは、一部の人々がこのような質問をし、サイトに初めて参加したときに、明白な解決策を見逃しているというだけのことです。
erdekhayser 2013

8
viewDidLoadメソッドで、if([self respondsToSelector:@selector(edgesForExtendedLayout)])self.edgesForExtendedLayout = UIRectEdgeNone;を追加します。これにより、ステータスバーの下からビューが強制的に開始されます。
Nandha 2013

回答:


629

iOS7以降、ビューコントローラーはデフォルトで全画面レイアウトを使用します。同時に、ビューのレイアウト方法をより詳細に制御できます。これは、次のプロパティで行われます。

edgeForExtendedLayout

基本的に、このプロパティでは、ビューのどちら側を拡張して画面全体をカバーできるかを設定します。をにプッシュするとUIViewControllerしますUINavigationController。そのビューコントローラーのビューがレイアウトされると、ナビゲーションバーが終わるところから始まりますが、このプロパティは、ビューのどの側(上、左、下、右)を拡張して画面全体に表示できるかを設定します。

例を見てみましょう:

UIViewController *viewController = [[UIViewController alloc] init];
viewController.view.backgroundColor = [UIColor redColor];
UINavigationController *mainNavigationController = [[UINavigationController alloc] initWithRootViewController:viewController];

ここではの値を設定していないedgesForExtendedLayoutため、デフォルト値(UIRectEdgeAll)が使用されるため、ビューはレイアウトを拡張して画面全体に表示されます。

これが結果です:

拡張レイアウトのエッジがない場合、ビューは画面全体に表示されます

ご覧のとおり、赤い背景はナビゲーションバーとステータスバーの背後に広がっています。

次に、その値をに設定してUIRectEdgeNone、ビューを画面全体に拡張しないようにビューコントローラーに指示します。

UIViewController *viewController = [[UIViewController alloc] init];
viewController.view.backgroundColor = [UIColor redColor];
viewController.edgesForExtendedLayout = UIRectEdgeNone;
UINavigationController *mainNavigationController = [[UINavigationController alloc] initWithRootViewController:viewController];

そしてその結果:

EdgesForExtendedLayoutが設定されている場合、ビューはナビゲーションのすぐ下にあります


automaticallyAdjustsScrollViewInsets

このプロパティは、ビューがのUIScrollViewようなである場合に使用されますUITableView。コンテンツ全体が表示されない場合はナビゲーションバーが終了するところからテーブルを開始する必要がありますが、同時にスクロール時にテーブルが画面全体を覆うようにする必要があります。その場合、edgesForExtendedLayoutナビゲーションバーが終了するとテーブルがスクロールし始め、その後ろに移動しないため、[なし] に設定しても機能しません。

ここでこのプロパティが役に立ちます。ビューコントローラーにインセットを自動的に調整させると(このプロパティをYESに設定し、デフォルト値も)、インセットがテーブルの上部に追加されるため、テーブルはナビゲーションの開始位置になりますバーは終了しますが、スクロールは画面全体をカバーします。

これは、NOに設定されている場合です。

テーブルは画面全体をスクロールしますが、最初は部分的にカバーされています

そしてYES(デフォルト):

テーブルは画面全体をスクロールし、ナビゲーションのすぐ下から始まります

どちらの場合も、テーブルはナビゲーションバーの後ろにスクロールしますが、2番目の場合(YES)は、ナビゲーションバーの下から始まります。


extendedLayoutIncludesOpaqueBars

この値は、前の値への単なる追加です。デフォルトでは、このパラメーターはNOに設定されています。ステータスバーが不透明の場合、ビューを拡張してステータスバーをカバーしても(edgesForExtendedLayoutまでUIRectEdgeAll)、ビューはステータスバーを含むように拡張されません。

値をYESに設定すると、ビューが再びステータスバーの下に移動できるようになります。

不明な点があればコメントを書いてお答えします。

iOSはどのUIScrollViewを使用するかをどのようにして知るのですか?

iOSは、ViewControllerのビューの最初のサブビュー(インデックス0のサブビュー)を取得し、それがのサブクラスの場合、Explain UIScrollViewされたプロパティをそれに適用します。

もちろん、これはUITableViewControllerデフォルトで機能することを意味します(UITableViewが最初のビューであるため)。


このプロパティを設定する必要があるのは、デフォルトのナビゲーションバーを表示している場合のみで、カスタマイズされたナビゲーションバーを表示している場合ではありませんよね?
Hemang 2013年

1
いいえ、iOSナビゲーションバーを使用するが、独自のデザインでは同じプロパティを使用する必要がある場合。ナビゲーションバーを最初から作成しただけでは、これらのプロパティは機能しません。
Antonio MG

ビュー全体に小さな黒っぽいレイヤーが表示されるのはなぜですか?助けてください?:/
aZtraL-EnForceR 2013

24
この説明は、iOS 7 UI移行ガイドよりもはるかに優れています。これはガイドを置き換えるだけでよく、私には意味がありませんでした。
サム14

2
デフォルトでは、extendedLayoutIncludesOpaqueBarsはNOではなくYESである必要があると思います。ビューの色(半透明性)を変更しても、レイアウトには影響しません。
ウラジミール・Slavík

15

ストーリーボードを使用しているかどうかはわかりませんが、使用している場合は、ビューコントローラーをステータスバーの下(下のバーの上)から開始するには、次のようにします。

IBでビューコントローラーを選択します。属性インスペクターで、[エッジの延長-上部バーの下]および[エッジの延長-下部バー]の選択を解除します。


OK。次に、Nandhaが上で提案したことは、プログラムで同じ結果を達成すると思います。viewDidLoadで機能しない場合は、viewDidLayoutSubviewsに移動する必要があります。
Ali Beadle 2013

拡張レイアウトに不透明なバーが含まれているかどうかを示します。@property(nonatomic、assign)BOOL extendedLayoutIncludesOpaqueBarsディスカッションデフォルト値はNOです。
Abdul Yasin 2013年

+1、ストーリーボードをチェックインするヒントを教えてくれました。そして、私は私の問題の半分を解決しました。
selva 2014年

10

私はストーリーボードを使用しており、上記のアドバイスを使用してうまくいきましたが、それを実装する方法が正確にわかりませんでした。以下は、推奨されるソリューションをViewControllerに配置することで問題を解決する方法の短い例です。

import Foundation
import UIKit

// This ViewController is connected to a view on a storyboard that 
// has a scrolling sub view.
class TheViewController: UIViewController {

  // Prepares the view prior to loading.  Putting it in viewDidAppear didn't work.
  override func viewWillAppear(animated: Bool) {

    // this method is an extension of the UIViewController 
    // so using self works as you might expect.
    self.automaticallyAdjustsScrollViewInsets = false

    // Default is "true" so this sets it to false tells it to use 
    // the storyboard as you have it placed
    // and not how it thinks it should place it.
  }

}

私の問題:自動調整がデフォルトでtrueに設定されているため、ストーリーボードのデザインとシミュレーターに違いが生じます 自動調整がデフォルトでtrueに設定されているため、ストーリーボードの設計とシミュレーターに違いが生じます

解決済み:上記のコードが適用され、自動調整がオフになりました。 上記のコードを適用し、自動調整をオフにします。


5
automaticallyAdjustsScrollViewInsetsをYESに設定する場合は、topGuideLayoutではなく、superviewにtop制約を設定する必要があります。
xmkevinchen 2015

5

この行を追加してこの問題を解決しましたが、私の問題はに関連してUIViewいました。UIScrollView

self.navigationController.navigationBar.translucent = NO;

2

automaticallyAdjustsScrollViewInsets プロパティは、何らかのスクロールビュー(テーブルビュー、コレクションビューなど)が次のいずれかである場合にのみ機能することを覚えておいて ください。

  • VCのビュー、または
  • このビューの最初のサブビュー

他の提案では、最初のサブビューであっても機能しませんが、ビュー階層には他のスクロールビューがあります。

編集(拡張子DIY)

これらの条件を満たせなくても同様の動作が必要な場合(スクロールビューの下に背景画像があるなど)、スクロールビューインセットを手動で調整できます。しかし、SOの周りで多くの人が提案しているように、44や64、20のように一定に設定しないでください。あなたはこれまでサイズを知ることができません。incall / gps / audio通知があり、ナビゲーションバーは常に44ポイントである必要はありません。

最良の解決策は、didLayoutSubviews lengthでlayoutGuide を使用することです。

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    scrollView.contentInset = UIEdgeInsets(top: topLayoutGuide.length, left: 0, bottom: 0, right: 0)
    scrollView.scrollIndicatorInsets = scrollView.contentInset
}

同じ方法でbottomLayoutGuideを使用できます。


そして、明らかにナビゲーションバーは半透明です。
Vojta Rujbr 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.