Подтвердить что ты не робот

UICollectionView в ландшафте на iPhone X

Когда iPhone X используется ландшафтом, вы должны проверить safeAreaInsets, чтобы сделать подходящие большие желоба слева и справа. UITableView имеет новое свойство insetsContentViewsToSafeArea (по умолчанию true), чтобы автоматически сохранять содержимое ячейки в безопасной области.

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

Простейшим способом обеспечения такого поведения является добавление в контроллер представления коллекции:

- (void)viewSafeAreaInsetsDidChange {
    [super viewSafeAreaInsetsDidChange];
    UIEdgeInsets contentInset = self.collectionView.contentInset;
    contentInset.left = self.view.safeAreaInsets.left;
    contentInset.right = self.view.safeAreaInsets.right;
    self.collectionView.contentInset = contentInset;
}

... при условии, что contentInset.left/right обычно равно нулю.

(ПРИМЕЧАНИЕ: да, для UICollectionViewController, который должен быть self.view.safeAreaInsets; в то время, когда это вызывается, изменение на safeAreaInsets странно еще не распространяется на self.collectionView)

Я что-то упустил? Этот шаблон достаточно прост, но он действительно необходим теперь для каждого вида коллекции, который касается края экрана. Кажется странным, что Apple не предоставила что-то, чтобы включить это по умолчанию.

4b9b3361

Ответ 1

В то время как Натан правильно относится к универсальности UICollectionView с различными макетами, меня в основном беспокоил случай "по умолчанию", когда один использует UICollectionViewFlowLayout.

Оказывается, iOS 11 добавила свойство sectionInsetReference к UICollectionViewFlowLayout. В официальной документации на нем в настоящее время отсутствует описание, однако заголовки описывают его как

Эталонная граница, что вставки секции будут определены как относительные. По умолчанию .fromContentInset.

ПРИМЕЧАНИЕ. Вставка содержимого всегда будет соблюдаться как минимум. Например, если параметр sectionInsetReference равен .fromSafeArea, но скорректированная вставка содержимого больше, чем комбинация безопасных областей и разделов, тогда содержимое раздела будет выровнено с вложением содержимого.

Возможные значения:

@available(iOS 11.0, *)
public enum UICollectionViewFlowLayoutSectionInsetReference : Int {
    case fromContentInset
    case fromSafeArea
    case fromLayoutMargins
}

и установка его на .fromSafeArea дает желаемые результаты, то есть когда первоначально в портретной ориентации:

первоначальный макет портрета

то при повороте в ландшафт, ячейки вставляются так, что они полностью находятся в безопасной зоне:

Картинная схема просмотра ландшафтного дизайна iPhone X

... ОДНАКО, в настоящее время существует ошибка, и при повороте назад к портрету после того, как представление было в ландшафте, оно продолжает действовать так, как если бы левые/правые параметры safeAreaInsets были установлены на значения ландшафта:

портретная макета после поворота из ландшафта

Я зарегистрировал радар (rdar://34491993) по этой проблеме.

Ответ 2

С той же проблемой. Это сработало для меня:

override func viewDidLoad() {
    if #available(iOS 11.0, *) {
        collectionView?.contentInsetAdjustmentBehavior = .always
    }
}

documentation для случая .always enum говорит:

В настройке содержимого всегда включайте вложения безопасной области.

Это решение работает правильно и в случае поворота телефона.

Ответ 3

Спасибо за помощь. Для моего подкласса UICollectionViewController я добавил следующее в viewDidLoad() (Swift 3):

if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
    if #available(iOS 11.0, *) {
        flowLayout.sectionInsetReference = .fromSafeArea
    }
}

Ответ 4

UICollectionView должен быть гибким для широкого разнообразия макетов. Наиболее распространенными макетами являются сетки с несколькими строками и столбцами, но можно создавать макеты без сетки с помощью UICollectionView.

UITableView, с другой стороны, предназначен для полноразмерных ячеек.

Следовательно, имеет смысл, что UITableView будет иметь встроенную поддержку для работы с безопасными вложенными вложениями, поскольку на нее всегда будут влиять макеты табличного вида. Поскольку UICollectionView использует персонализированные макеты, имеет смысл решить эти проблемы на основе каждой реализации, вместо того чтобы пытаться обеспечить решение одного размера для всех.