it-roy-ru.com

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

34
Wes Campaigne

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

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

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

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

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

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

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

 initial portrait layout

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

 iPhone X landscape collection view layout

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

 portrait layout following rotation from landscape

Я подал радар ( rdar: // 34491993 ) относительно этой проблемы.

38
Wes Campaigne

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

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

Документация для случая перечисления .always гласит: 

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

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

47
petrsyn

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

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

Учтите, что вышеупомянутые решения не решают случай, когда ваши представления ячейки коллекции (и подпредставления, которые ограничены передними или задними краями ее ячейки) имеют полную ширину к границам представления коллекции и не настроены на подчинение Безопасная область Руководства по макету

Примечание. Ответ @petrsyn делает вставку заголовка сбоку, чего может не хотеть большинство людей, а ответ @Wes Campaigne не совсем корректно работает для ячеек полной ширины, где подпредставление прикреплено к ведущему или завершающему. края клетки. 

Крайне важно, особенно для тех, кто работает в более старых проектах, установить для файлов Xib и Storyboard значение Использовать руководства по макету безопасной области , а затем использовать автоматическое расположение, чтобы установить ограничения, соответствующие безопасным областям, или выполнить аналогичные действия в коде.

1
iAmcR

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

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

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

0
nathangitter