web-dev-qa-db-ger.com

UICollectionView in Landschaft auf dem iPhone X

Wenn das iPhone X im Querformat verwendet wird, sollten Sie safeAreaInsets überprüfen, um links und rechts entsprechend große Dachrinnen zu erstellen. UITableView verfügt über die neue insetsContentViewsToSafeArea-Eigenschaft (Standardeinstellung true), um den Zellinhalt automatisch im sicheren Bereich zu halten.

Ich bin überrascht, dass UICollectionView nichts ähnliches zu haben scheint. Ich würde erwarten, dass für eine vertikal durchlaufende Sammlungsansicht die linke und rechte Seite in der sicheren Zone im Querformat eingefügt werden würde (und umgekehrt würde eine horizontal scrollende Sammlungsansicht eingefügt werden, wenn dies im Hochformat erforderlich ist).

Der einfachste Weg, um dieses Verhalten sicherzustellen, scheint das Hinzufügen zum Auflistungsansicht-Controller zu sein:

- (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;
}

... vorausgesetzt, dass contentInset.left/right normalerweise null ist.

(HINWEIS: Ja, für einen UICollectionViewController muss dies self.view.safeAreaInsets sein; zum Zeitpunkt des Aufrufs wurde die Änderung an safeAreaInsets seltsamerweise noch nicht an self.collectionView weitergegeben.)

Fehlt mir etwas? Diese Boilerplate ist einfach genug, aber für die jede - Sammlungsansicht, die eine Bildschirmkante berührt, ist sie jetzt effektiv erforderlich. Es scheint wirklich merkwürdig, dass Apple dies nicht standardmäßig aktiviert hat.

34
Wes Campaigne

Während Nathan die Vielseitigkeit von UICollectionView mit verschiedenen Layouts richtig einschätzt, war ich hauptsächlich besorgt über den "Standard" -Fall, in dem UICollectionViewFlowLayout verwendet wird.

Es stellte sich heraus, dass iOS 11 eine sectionInsetReference-Eigenschaft zu UICollectionViewFlowLayout hinzugefügt hat. In der offiziellen Dokumentation fehlt derzeit eine Beschreibung, die Kopfzeilen beschreiben sie jedoch als

Die Referenzgrenze, zu der die Abschnittsinsets als relativ definiert werden. Standardeinstellung ist .fromContentInset.

HINWEIS: Der Inhalt wird immer mindestens eingehalten. Wenn beispielsweise die sectionInsetReference gleich .fromSafeArea ist, der angepasste Inhalt jedoch größer ist als die Kombination aus dem sicheren Bereich und den Abschnitten, wird der Abschnittsinhalt stattdessen an der Inhaltseinstellung ausgerichtet.

Die möglichen Werte sind

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

und das Einstellen auf .fromSafeArea erzeugt die gewünschten Ergebnisse, d. h.

 initial portrait layout

beim Drehen in die Landschaft werden die Zellen so eingesetzt, dass sie sich vollständig im sicheren Bereich befinden:

 iPhone X landscape collection view layout

... JEDOCH gibt es derzeit einen Fehler, und wenn Sie zurück zum Portrait drehen, nachdem die Ansicht im Querformat war, wirkt sie weiterhin so, als wären die linken/rechten safeAreaInsets auf die Landschaftswerte gesetzt:

 portrait layout following rotation from landscape

Ich habe ein Radargerät ( rdar: // 34491993 ) zu diesem Problem angemeldet.

38
Wes Campaigne

Das gleiche Problem haben. Das hat für mich funktioniert:

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

Die Dokumentation für die Enzykluft .always sagt: 

Beziehen Sie immer die sicheren Bereichseinsätze in die Inhaltsanpassung ein.

Diese Lösung funktioniert auch dann richtig, wenn das Telefon gedreht wird.

47
petrsyn

Danke an oben für die Hilfe. Für meine UICollectionViewController-Unterklasse habe ich viewDidLoad () (Swift 3) Folgendes hinzugefügt:

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

Die oben genannten Lösungen lösen jedoch nicht den Fall, in dem Ihre Ansichten der Sammlungszelle (und Unteransichten, die auf die Vorder- oder Hinterkanten der Zelle beschränkt sind) die gesamte Breite der Sammlungsansichtsgrenzen haben und nicht auf Safe Area festgelegt sind Layout Guides

Hinweis: Die Antwort von @petrsyn bewirkt, dass die Kopfzeile von den Seiten eingefügt wird, was die meisten Benutzer möglicherweise nicht möchten, und die Antwort von @Wes Campaigne funktioniert für Zellen mit voller Breite, bei denen eine Unteransicht mit der führenden oder nachgestellten Zeile verbunden ist, nicht richtig Kanten der Zelle. 

Insbesondere für diejenigen, die aus älteren Projekten stammen, müssen Sie Ihre Xib- und Storyboard-Dateien auf Use Safe Area Layout Guides setzen und dann das automatische Layout verwenden, um Einschränkungen für die sicheren Bereiche zu erstellen oder ähnliches im Code auszuführen.

1
iAmcR

UICollectionView soll für eine Vielzahl von Layouts flexibel sein. Die gebräuchlichsten Layouts sind Raster mit mehreren Zeilen und Spalten. Es ist jedoch möglich, Layouts ohne Raster mit UICollectionView zu erstellen.

UITableView ist dagegen für Zellen voller Breite konzipiert.

Daher ist es sinnvoll, dass UITableView eine integrierte Unterstützung für den Umgang mit Insets für sichere Bereiche hat, da Layouts von Tabellensichten immer davon betroffen sind. Da UICollectionView benutzerdefinierte Layouts verwendet, ist es sinnvoll, diese Probleme pro Implementierung zu lösen, anstatt zu versuchen, eine einheitliche Lösung bereitzustellen.

0
nathangitter