web-dev-qa-db-ja.com

iOS7でautomaticallyAdjustsScrollViewInsets、extendedLayoutIncludesOpaqueBars、edgesForExtendedLayoutの違いを説明する

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

これら3つのプロパティautomaticallyAdjustsScrollViewInsetsextendedLayoutIncludesOpaqueBarsedgesForExtendedLayoutを取得できません。

たとえば、View Controllerをステータスバーの下に表示させようとしていますが、達成できません。

240
user1010819

IOS 7以降、View Controllerはデフォルトで全画面レイアウトを使用します。同時に、あなたはそれがそのビューをどのようにレイアウトするかについてより多くのコントロールを持っています、そしてそれはそれらのプロパティで行われます:

edgesForExtendedLayout

基本的に、このプロパティを使用して、画面全体をカバーするようにビューのどちら側を拡大できるかを設定します。 UIViewControllerUINavigationControllerにプッシュすると想像してください。そのView Controllerのビューがレイアウトされると、ナビゲーションバーが終わる位置から開始されますが、このプロパティはビューのどの辺(上、左、下、右)を画面全体に広げることができるかを設定します。

例を見てみましょう。

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

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

これが結果です。

without edges for extended layout, the view fills the whole screen

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

これで、その値をUIRectEdgeNoneに設定することになります。そのため、ビューを拡張しないようにView Controllerに指示しています。

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

そしてその結果:

with edgesForExtendedLayout set, the view is just under the navigation

automaticallyAdjustsScrollViewInsets

このプロパティは、ビューがUIScrollViewのようにUITableViewなどの場合に使用されます。あなたはあなたのテーブルをナビゲーションバーが終わるところから始めることを望みます、そうでなければあなたは全体のコンテンツを見ることはしないでしょうが同時にスクロールするときあなたのテーブルはスクリーン全体をカバーしたいです。その場合、ナビゲーションバーの最後の部分でテーブルがスクロールし始め、後ろに移動しないため、edgesForExtendedLayoutをNoneに設定しても機能しません。

このプロパティが便利になるのは、ビューコントローラに自動的にインセットを調整させる(このプロパティをYES、デフォルト値に設定する)と、テーブルの最上部にインセットが追加されるため、ナビゲーションが開始される場所から開始されます。バーは終了しますが、スクロールは画面全体を覆います。

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

the table will scroll over the whole screen, but starts out partially covered

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

the table scrolls over the whole screen, and starts just under the navigation

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

extendedLayoutIncludesOpaqueBars

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

値をYESに設定すると、ビューはステータスバーの下に戻ることができます。

よくわからない場合は、コメントを書いて答えてください。

どのようにしてiOSはUIScrollViewを使うべきかを知りますか?

iOSは、ViewControllerのビューの最初のサブビュー、つまりインデックス0のサブビューを取得し、それがUIScrollViewのサブクラスである場合は、説明されているプロパティをそれに適用します。

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

601
Antonio MG

ストーリーボードを使用しているかどうかはわかりませんが、使用している場合は、View Controllerをステータスバーの下(および下のバーの上)から開始するようにします。

IBでView Controllerを選択します。属性インスペクタで、[エッジを延長 - 上のバーの下に]および[エッジを延長 - 下のバーの下]を選択解除します。

15
Ali Beadle

私は絵コンテを使っていて、上のアドバイスを使ってうまくいきましたが、それを実装する方法が正確にはわからない。下記はSwiftの簡単な例で、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に設定されているため、ストーリーボードのデザインとシミュレータの間に違いが生じる Auto Adjust set to true by default causing a difference between storyboard design and simulator

解決済み:上記のコードを適用し、自動調整をオフにした。 Code above applied, turning off the auto-adjust.

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

self.navigationController.navigationBar.translucent = NO;
5
user3430340

automaticallyAdjustsScrollViewInsetsプロパティは、ある種のスクロールビュー(テーブルビュー、コレクションビューなど)がいずれかの場合にのみ機能することに注意してください。

  • VCの見方
  • このビューの最初のサブビュー

他は、それが最初のサブビューであってもそれが最もうまくいくことを示唆しました、しかしビュー階層に他のスクロールビューがあります。

EDIT(拡張子DIY)

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

私は最善の解決策はdidLayoutSubviewsでlayoutGuide lengthを使うことだと思います。

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

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

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

2
Vojta Rujbr