web-dev-qa-db-fra.com

Modifier la taille de UICollectionViewCell selon différentes orientations de périphérique

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?

99
Fmessina

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.

200
followben

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];
}
33
Hai Feng Kao

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];
    }
}
13
Fiveagle

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.

8
Dannie P

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)
}
7
DogCoffee

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);
    }   
    }     
}
2
toofani