45 votes

UICollectionView en paysage sur iPhone X

Lorsque l'iPhone X est utilisé paysage, vous êtes censé vérifier safeAreaInsets de faire assez grande gouttières sur la gauche et la droite. UITableView a la nouvelle - insetsContentViewsToSafeArea de la propriété (par défaut à true) pour conserver automatiquement le contenu de la cellule dans la zone de sécurité.

Je suis surpris que UICollectionView semble pas avoir quelque chose de similaire. Je m'attends à que pour une verticale de défilement vue de collection, les côtés gauche et droit serait encart de la zone de sécurité en mode paysage (et à l'inverse, une horizontale de défilement de la collection de point de vue, en médaillon, si nécessaire en mode portrait).

La façon la plus simple d'assurer ce comportement semble être à ajouter à la collection-vue-contrôleur:

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

... en supposant contentInset.gauche/droite sont normalement zéro.

(NOTE: oui, pour un UICollectionViewController, qui doit être self.view.safeAreaInsets; à l'époque on l'appelle, le changement d' safeAreaInsets a curieusement pas encore propagé à l' self.collectionView)

Ai-je raté quelque chose? Que passe-partout est assez simple, mais il est effectivement nécessaire maintenant pour chaque vue de collection qui touche un bord de l'écran. Il semble vraiment bizarre qu'Apple n'ait pas fournir quelque chose pour activer cette fonction par défaut.

72voto

petrsyn Points 739

Avoir le même problème. Cela a fonctionné pour moi:

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

La documentation relative au cas .always enum indique:

Toujours inclure les encarts de la zone de sécurité dans l'ajustement du contenu.

Cette solution fonctionne correctement également dans le cas où le téléphone est pivoté.

42voto

Wes Campaigne Points 774

Alors que Nathan est correct au sujet de la polyvalence de UICollectionView avec différentes mises en page, j'étais surtout préoccupé par le "par défaut" cas où l'on utilise UICollectionViewFlowLayout.

S'avère, iOS 11 a ajouté une sectionInsetReference de la propriété d' UICollectionViewFlowLayout. La documentation officielle sur il manque actuellement une description, même les en-têtes de le décrire comme

La référence limite de la section des encarts seront définis que par rapport à. Par défaut, .fromContentInset.

REMARQUE: le Contenu de l'encart sera toujours respecté au minimum. Par exemple, si le sectionInsetReference est égal à .fromSafeArea, mais le réglage de la teneur en médaillon est plus grande que la combinaison de la zone de sécurité et à la section des encarts, puis le contenu de la section sera aligné avec le contenu de l'encart de la place.

Les valeurs possibles sont

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

et la valeur .fromSafeArea produit les résultats escomptés, c'est à dire, lorsque initialement en orientation portrait:

initial portrait layout

ensuite, lors de la rotation du paysage, les cellules sont positionnés de telle sorte qu'ils sont entièrement à l'intérieur de la zone de sécurité:

iPhone X landscape collection view layout

... CEPENDANT, il y a actuellement un bug, et lors de la rotation arrière pour le portrait après le point de vue a été, dans le paysage, il continue d'agir comme si la gauche/droite safeAreaInsets sont définies sur les valeurs du paysage:

portrait layout following rotation from landscape

J'ai déposé un radar (rdar://34491993) au sujet de ce problème.

12voto

anorskdev Points 1124

Merci à ci-dessus pour l'aide. Pour ma sous-classe UICollectionViewController, j'ai ajouté ce qui suit à viewDidLoad () (Swift 3):

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

1voto

iAmcR Points 369

Bare à l'esprit les solutions ci-dessus ne résolvent pas le cas où votre collection de cellules de vues (et les sous-vues, qui sont limitées à sa cellule bords avant et arrière) sont en pleine largeur de l'affichage de la collection de limites et qui ne sont pas définis à obéir à la Zone de Sécurité repères de Mise en page.

Remarque: La réponse par @petrsyn rend l'en-tête en retrait de l'côtés, la plupart des gens ne le voulons pas et la réponse par @Wes Campaigne ne fonctionne pas correctement pour l'ensemble de la largeur des cellules, d'où une sous-vue est attaché les bords avant et arrière de la cellule.

Il est impératif, en particulier pour ceux qui viennent de projets plus anciens, pour régler votre Xib et Storyboard fichiers pour l'Utilisation de la Zone de Sécurité repères de Mise en page , puis utiliser la mise en page automatique de placer des contraintes respectives de la les zones de sécurité ou de faire les mêmes dans le code.

0voto

nathangitter Points 6663

UICollectionView est destiné à être flexible pour une grande variété de mises en page. Les plus communes sont mises en réseaux avec plusieurs lignes et colonnes, mais il est possible de créer des non-grille de mise en page UICollectionView.

UITableView, d'autre part, est conçu pour la pleine largeur des cellules.

Par conséquent, il est logique qu' UITableView aurait une prise en charge intégrée pour traiter de la zone de sécurité encarts, depuis la vue de la table mise en page doit toujours être touchés par elle. Parce qu' UICollectionView utilise des mises en page personnalisées, il est logique pour résoudre ces problèmes par la mise en œuvre de base au lieu d'essayer de fournir un one-size-fits-all solution.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X