Объясняя разницу между автоматическими AdjustsScrollViewInsets, extendedLayoutIncludeOpaqueBars, edgeForExtendedLayout в iOS7


250

Я много читал о переходе пользовательского интерфейса iOS7.

Я не могу получить то , что эти три свойства automaticallyAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars, edgesForExtendedLayout??

Например, я пытаюсь заставить мои контроллеры представления запускаться ниже строки состояния, но я не в состоянии достигнуть этого.


5
и почему вы думаете, что я не читал это? .. Проблема в том, что не работает, как ожидалось, так как я не понял это хорошо !! .. вот причина
user1010819

1
Оооо, я неправильно понял, что вы там говорили. Я не пытался звучать покровительственно, просто, когда некоторые люди задают подобные вопросы, и являются новичками на сайте, они упускают очевидные решения.
эрдехайсер

8
В своем методе viewDidLoad добавьте if ([self RespondsToSelector: @selector (dgeForExtendedLayout)]) self.edgesForExtendedLayout = UIRectEdgeNone; что заставит ваш взгляд начать ниже строки состояния.
Нанда

Ответы:


629

Начиная с iOS7, контроллеры представления по умолчанию используют полноэкранный макет. В то же время у вас есть больший контроль над тем, как он размещает свои представления, и это делается с этими свойствами:

edgesForExtendedLayout

По сути, с помощью этого свойства вы устанавливаете, какие стороны вашего вида могут быть расширены, чтобы охватить весь экран. Представь, что ты толкаешь 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];

И результат:

с установленным edgeForFortendedLayout, представление находится под навигацией


automaticallyAdjustsScrollViewInsets

Это свойство используется, когда ваше представление является UIScrollViewили похожим, например UITableView. Вы хотите, чтобы ваша таблица начиналась там, где заканчивается панель навигации, потому что вы не увидите весь контент, если нет, но в то же время вы хотите, чтобы ваша таблица покрывала весь экран при прокрутке. В этом случае установка edgesForExtendedLayoutNone не будет работать, потому что ваша таблица начнет прокручиваться в том месте, где заканчивается панель навигации, и не будет идти за ней.

Вот где это свойство пригодится, если вы позволите контроллеру представления автоматически корректировать вставки (устанавливая это свойство в YES, также значение по умолчанию), он добавит вставки в верхнюю часть таблицы, поэтому таблица начнется там, где происходит навигация. полоса заканчивается, но прокрутка покроет весь экран.

Это когда НЕТ:

таблица будет прокручиваться по всему экрану, но начинается частично

И ДА (по умолчанию):

таблица прокручивается по всему экрану и запускается прямо под навигацией

В обоих случаях таблица прокручивается за панелью навигации, но во втором случае (ДА) она запускается из-под панели навигации.


extendedLayoutIncludesOpaqueBars

Это значение является просто дополнением к предыдущим. По умолчанию для этого параметра установлено значение NO. Если строка состояния непрозрачна, представления не будут расширены для включения строки состояния, даже если вы расширили представление, чтобы покрыть его ( edgesForExtendedLayoutдо UIRectEdgeAll).

Если вы установите значение YES, это позволит представлению снова перейти под строку состояния.

Если что-то не понятно, напишите комментарий и я на него отвечу.

Как iOS узнает, что использовать UIScrollView?

iOS получает первое подпредставление в представлении ViewController, которое имеет индекс 0, и, если оно является подклассом, UIScrollViewприменяет к нему объясненные свойства.

Конечно, это означает, что UITableViewControllerработает по умолчанию (так как UITableViewэто первый вид).


Нам нужно установить эти свойства только в том случае, если мы показываем панель навигации по умолчанию, а не в том случае, если это настраиваемая панель навигации, верно?
Hemang

1
Нет, если вы используете панель навигации iOS, но с вашим собственным дизайном вам нужно будет использовать те же свойства. Если вы просто создаете панель навигации на пустом месте, то эти свойства не будут работать.
Антонио М.Г.

Я не понимаю, почему появляется маленький черноватый слой по всему виду? Пожалуйста помоги? : /
aZtraL-EnForceR

24
Это объяснение намного лучше, чем Руководство по переходу с iOS 7. Это должно просто заменить руководство, которое не имеет смысла для меня.
Сэм

2
Я думаю, что extendedLayoutIncludesOpaqueBars по умолчанию должно быть ДА, а не НЕТ. Изменение цвета вида (прозрачность) не должно влиять на макет.
Владимир Славик

15

Не уверен, используете ли вы раскадровки, но если это так, чтобы ваши контроллеры представления запускались под строкой состояния (и над нижней панелью):

Выберите контроллер представления в IB. В инспекторе атрибутов отмените выбор «Расширить края - под верхними панелями» и «Расширить края - под нижними панелями».


ХОРОШО. Тогда я думаю, что то, что предложил Нанда, достигнет того же результата программно. Если он не работает в viewDidLoad, возможно, его необходимо переместить в viewDidLayoutSubviews.
Али Бидл

Указывает, содержит ли расширенный макет непрозрачные столбцы. @property (nonatomic, assign) BOOL extendedLayoutIncludesOpaqueBars Обсуждение Значение по умолчанию - NO.
Абдул Ясин

+1, вы дали мне подсказку проверить раскадровку. И я решил свою половину своей проблемы.
Сельва

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
если вы автоматически включитеAdjustsScrollViewInsets как YES, то вы должны установить ограничение top для суперпредставления, а не topGuideLayout.
xmkevinchen

5

Я решил эту проблему, добавив эту строку, но моя проблема была связана с UIView, неUIScrollView

self.navigationController.navigationBar.translucent = NO;

2

Просто помните, что automaticallyAdjustsScrollViewInsets свойство работает, только если какое-либо представление прокрутки (представление таблицы, представление коллекции, ...)

  • По мнению ВК, или
  • Первое подпредставление этой точки зрения

Другие предположили, что это работает, даже если это первое подпредставление, но в иерархии представлений есть другие представления прокрутки.

РЕДАКТИРОВАТЬ (расширение DIY)

Если вам нужно подобное поведение, даже если вы не можете выполнить эти условия (например, у вас есть фоновое изображение под видом прокрутки), вы можете вручную настроить вкладки вида прокрутки. Но, пожалуйста, не устанавливайте его постоянным, как 44 или 64 или даже 20, как многие предлагают вокруг SO. Вы не можете знать размер когда-либо. Там может быть incall / GPS / аудио-уведомление, панель навигации не всегда должна быть 44 пункта и т. Д.

Я думаю, что лучшее решение - это использовать layoutGuide lengthв didLayoutSubviews:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

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

Вы можете использовать bottomLayoutGuide таким же образом.


И, очевидно, панель навигации является полупрозрачной.
Войта Руйбр,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.