J'utilise un UICollectionView
avec UICollectionViewFlowLayout
.
Je règle la taille de chaque cellule à travers le
collectionView:layout:sizeForItemAtIndexPath:
Lors du passage de portrait en paysage, je voudrais ajuster la taille de chaque cellule pour l'adapter complètement à la taille de CollectionView, sans laisser d'espace de remplissage entre les cellules.
Des questions:
1) Comment changer la taille d'une cellule après un événement de rotation?
2) Et, mieux encore, comment faire la mise en page où les cellules correspondent toujours à la taille entière de l'écran?
1) Vous pouvez gérer et échanger plusieurs objets de mise en page, mais il existe un moyen plus simple. Ajoutez simplement ce qui suit à votre sous-classe UICollectionViewController
et ajustez les tailles selon vos besoins:
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
// Adjust cell size for orientation
if (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
return CGSizeMake(170.f, 170.f);
}
return CGSizeMake(192.f, 192.f);
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[self.collectionView performBatchUpdates:nil completion:nil];
}
Appeler -performBatchUpdates:completion:
invalidera la mise en page et redimensionnera les cellules avec une animation (vous pouvez simplement passer nil aux deux paramètres de bloc si vous n'avez aucun ajustement supplémentaire à effectuer).
2) Au lieu de coder en dur les tailles d’élément dans -collectionView:layout:sizeForItemAtIndexPath
, divisez simplement la hauteur ou la largeur des limites de collectionView par le nombre de cellules que vous souhaitez adapter à l'écran. Utilisez la hauteur si votre collectionView défile horizontalement ou la largeur si elle défile verticalement.
Si vous ne voulez pas d'animations supplémentaires apportées par performBatchUpdates:completion:
, utilisez simplement invalidateLayout
pour forcer le rechargement de collectionViewLayout.
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
[self.collectionView.collectionViewLayout invalidateLayout];
}
J'ai résolu en utilisant deux UICollectionViewFlowLayout. Un pour portrait et un pour paysage. Je les attribue à ma collectionVoir dinamically dans -viewDidLoad
self.portraitLayout = [[UICollectionViewFlowLayout alloc] init];
self.landscapeLayout = [[UICollectionViewFlowLayout alloc] init];
UIInterfaceOrientation orientationOnLunch = [[UIApplication sharedApplication] statusBarOrientation];
if (UIInterfaceOrientationIsPortrait(orientationOnLunch)) {
[self.menuCollectionView setCollectionViewLayout:self.portraitLayout];
} else {
[self.menuCollectionView setCollectionViewLayout:self.landscapeLayout];
}
Puis j'ai simplement modifié mes méthodes collectionViewFlowLayoutDelgate comme ceci
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
CGSize returnSize = CGSizeZero;
if (collectionViewLayout == self.portraitLayout) {
returnSize = CGSizeMake(230.0, 120.0);
} else {
returnSize = CGSizeMake(315.0, 120.0);
}
return returnSize;
}
Enfin, je passe d'une mise en page à une autre en rotation
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
if (UIInterfaceOrientationIsPortrait(fromInterfaceOrientation)) {
[self.menuCollectionView setCollectionViewLayout:self.landscapeLayout animated:YES];
} else {
[self.menuCollectionView setCollectionViewLayout:self.portraitLayout animated:YES];
}
}
Il existe un moyen simple de définir la taille de la cellule de la vue de collection:
UICollectionViewFlowLayout *layout = (id) self.collectionView.collectionViewLayout;
layout.itemSize = CGSizeMake(cellSize, cellSize);
Je ne sais pas si c'est animable cependant.
Swift: Cellule de vue de collection représentant n% de la hauteur de l'écran
J'avais besoin d'une cellule représentant un certain pourcentage de la hauteur de la vue et redimensionnant avec la rotation du périphérique.
Avec l'aide d'en haut, voici la solution
override func viewDidLoad() {
super.viewDidLoad()
automaticallyAdjustsScrollViewInsets = false
// if inside nav controller set to true
}
override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
collectionViewLayout.invalidateLayout()
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSize(width: 100, height: collectionView.frame.height * 0.9)
}
Si vous utilisez autolayout
, il vous suffit de invalidate layout
dans votre contrôleur de vue lors de la rotation et ajustez offset
dans votre sous-classe de présentation de flux.
Donc, dans votre contrôleur de vue -
override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
self.galleryCollectionView.collectionViewLayout.invalidateLayout()
}
Et dans votre FlowLayout Subclass
override func prepareLayout() {
if self.collectionView!.indexPathsForVisibleItems().count > 0{
var currentIndex : CGFloat!
currentIndex = CGFloat((self.collectionView!.indexPathsForVisibleItems()[0] as! NSIndexPath).row)
if let currentVal = currentIndex{
self.collectionView!.contentOffset = CGPointMake(currentIndex * self.collectionView!.frame.width, self.collectionView!.contentOffset.y);
}
}
}