J'utilise un UICollectionView
avec UICollectionViewFlowLayout
.
Je définis la taille de chaque cellule à travers le
collectionView:layout:sizeForItemAtIndexPath:
Lorsque je passe du mode portrait au mode paysage, je souhaite ajuster la taille de chaque cellule pour l'adapter complètement à la taille de la collection, sans laisser d'espace entre les cellules.
Des questions:
1) Comment changer la taille d'une cellule après un événement de rotation?
2) Et, encore mieux, comment faire la layout où les cellules correspondent toujours à la taille de l'écran?
1) Vous pouvez maintenir et échanger plusieurs objects de layout, mais il existe un moyen plus simple. Ajoutez simplement ce qui suit à votre sous-class 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 layout et resizea les cellules avec animation (vous pouvez simplement passer nil aux deux params de bloc si vous n'avez pas d'ajustements supplémentaires à effectuer).
2) Au lieu de coder en dur les tailles d'éléments dans -collectionView:layout:sizeForItemAtIndexPath
, il suffit de split la hauteur ou la largeur des limites de collectionView par le nombre de cellules que vous voulez ajuster à l'écran. Utilisez la hauteur si votre collection défile horizontalement ou la largeur si elle défile verticalement.
Si vous ne voulez pas d'animations supplémentaires apscopes par performBatchUpdates:completion:
utilisez simplement invalidateLayout
pour forcer le recouvrement de collectionViewLayout.
- (void)viewWillLayoutSubviews { [super viewWillLayoutSubviews]; [self.collectionView.collectionViewLayout invalidateLayout]; }
J'ai résolu en utilisant deux UICollectionViewFlowLayout. Un pour le portrait et un pour le paysage. Je les assigne à ma collectionVoir dinamiquement 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]; }
Ensuite, j'ai simplement modifié mes methods de 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 layout à 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 animé.
Swift: Collection Afficher la cellule dont n% de la hauteur de l'écran
J'avais besoin d'une cellule qui avait un certain pourcentage de hauteur de vue, et resize avec la rotation de l'appareil.
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 la invalidate layout
en invalidate layout
autolayout
Vous autolayout
juste besoin d' invalidate layout
dans votre controller de vue lors de la rotation et d'ajuster le offset
dans votre sous-class de disposition de stream.
Donc, dans votre vue controller –
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); } } }