it-swarm.com.ru

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

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

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

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

240
user1010819

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

edgesForExtendedLayout

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

Давайте посмотрим на это на примере:

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, поэтому вы говорите контроллеру представления не расширять представление, чтобы охватить экран:

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, также значение по умолчанию), он добавит вставки в верхнюю часть таблицы, поэтому таблица начнется там, где происходит навигация. полоса заканчивается, но прокрутка покроет весь экран.

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

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

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

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

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

extendedLayoutIncludesOpaqueBars

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

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

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

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

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

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

601
Antonio MG

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

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

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.

10
Christopher Wade Cantley

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

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

Просто помните, что свойство 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 таким же образом.

2
Vojta Rujbr