web-dev-qa-db-fra.com

Comment obtenir la taille de mise en page automatique des UICollectionViewCells dans iOS 8? (systemLayoutSizeFittingSize renvoie la taille avec une hauteur nulle dans iOS 8)

Depuis iOS 8, [UIColletionViewCell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] renvoie une taille de hauteur 0. 

Voici ce que le code fait:

Pour déterminer la taille d'une cellule dans une UICollectionView dans iOS 7, j'utilise systemLayoutSizeFittingSize: dans une cellule définie dans un fichier xib à l'aide de la présentation automatique. La taille dépend de la taille de la police UILabel étant une sous-vue de UICollectionViewCell dans mon fichier xib. La police de l'étiquette est définie sur UIFontTextStyleBody. Donc, fondamentalement, la taille de la cellule dépend du paramètre de taille de police défini dans iOS 7. 

Voici le code lui-même:

+ (CGSize)cellSize {
    UINib *nib = [UINib nibWithNibName:NSStringFromClass([MyCollectionViewCell class]) bundle:nil];

    // Assumption: The XIB file only contains a single root UIView.
    UIView *rootView = [[nib instantiateWithOwner:nil options:nil] lastObject];

    if ([rootView isKindOfClass:[MyCollectionViewCell class]]) {
        MyCollectionViewCell *sampleCell = (MyCollectionViewCell*)rootView;
        sampleCell.label.text = @"foo"; // sample text without bar

        [sampleCell setNeedsLayout];
        [sampleCell layoutIfNeeded];

        return [sampleCell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    }

    return CGSizeZero;

}

Cela fonctionne parfaitement dans iOS 7 mais pas dans iOS 8. Malheureusement, je ne sais pas pourquoi. 

Comment puis-je obtenir la taille de la mise en page automatique des UICollectionViewCells dans iOS 8?

PS: Utilisation 

 return [sampleCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

au lieu de

 return [sampleCell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

comme quelqu'un pourrait le suggérer, cela ne fait aucune différence. 

25
martn_st

Cela ressemble officiellement à un bogue: j'ai déposé un rapport qui était fermé en tant que duplicata de celui-ci

Signaler la fin de la bêta 6.

[Update: fonctionne correctement dans le fichier GM d'iOS 8 et le bogue a été fermé par Apple.]

7
Philip McDermott

Ce que vous devez faire, c'est encapsuler tout votre contenu dans une vue de conteneur, puis appeler:

return [sampleCell.containerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

Votre cellule devrait ressembler à ceci: cellule -> conteneurView -> vues secondaires

Cela fonctionne à la fois sur iOS 7 et iOS 8. 

Soi-disant sur ios8, tout ce que vous avez à faire est de définir estimationSize & cell automatiquement la taille automatiquement Apparemment, cela ne fonctionne pas à partir de la version 6. 

8
Triet Luong

Nous utilisons une solution de rechange pour l'instant, copiée ci-dessous. Espérons que ces problèmes seront résolus avant la sortie de iOS 8 et que nous pourrons les supprimer. (Le kludge suppose la connaissance du comportement implicite de ContentView d’Apple et nous devons pirater les références des points de vente IB aux contraintes que nous transférons.)

Nous remarquons qu'ils suppriment également tous les masques autoresizing des storyboards/NIB lors de la mise à niveau, ce qui est logique dans la mesure où il est supposé être une présentation automatique, mais les vues de collection renvoient toujours aux ressorts et aux entretoises. Peut-être que cela a été négligé dans la purge?

--Dan

/**
 Kludge around cell sizing issues for iOS 8 and deployment to iOS 7 when compiled for 8.  Call this on the collection view cell before it is used, such as in awakeFromNib.  Because this manipulates top-level constraints, any references to such initial constraints, such as from IB outlets, will be invalidated.

 Issue 1: As of iOS 8 Beta 5, systemLayoutSizeFittingSize returns height 0 for a UICollectionViewCell.  In IB, cells have an implicit contentView, below which views placed in IB as subviews of the cell are actually placed.  However, constraints set between these subviews and its superview are placed on the cell, rather than the contentView (which is their actual superview).  This should be OK, as a constraint among items may be placed on any common ancestor of those items, but this is not playing Nice with systemLayoutSizeFittingSize.  Transferring those constraints to be on the contentView seems to fix the issue.

 Issue 2: In iOS 7, prior to compiling against iOS 8, the resizing mask of the content view was being set by iOS to width+height.  When running on iOS 7 compiled against iOS 8 Beta 5, the resizing mask is None, resulting in constraints effecting springs for the right/bottom margins.  Though this starts out the contentView the same size as the cell, changing the cell size, as we do in the revealing list, is not tracked by changing it's content view.  Restore the previous behavior.

 Moving to dynamic cell sizing in iOS 8 may circumvent this issue, but that remedy isn't available in iOS 7.
*/
+ (void)kludgeAroundIOS8CollectionViewCellSizingIssues:(UICollectionViewCell *)cell {

    // transfer constraints involving descendants on cell to contentView
    UIView *contentView = cell.contentView;
    NSArray *cellConstraints = [cell constraints];
    for (NSLayoutConstraint *cellConstraint in cellConstraints) {
        if (cellConstraint.firstItem == cell && cellConstraint.secondItem) {
            NSLayoutConstraint *parallelConstraint = [NSLayoutConstraint constraintWithItem:contentView attribute:cellConstraint.firstAttribute relatedBy:cellConstraint.relation toItem:cellConstraint.secondItem attribute:cellConstraint.secondAttribute multiplier:cellConstraint.multiplier constant:cellConstraint.constant];
            parallelConstraint.priority = cellConstraint.priority;
            [cell removeConstraint:cellConstraint];
            [contentView addConstraint:parallelConstraint];
        } else if (cellConstraint.secondItem == cell && cellConstraint.firstItem) {
            NSLayoutConstraint *parallelConstraint = [NSLayoutConstraint constraintWithItem:cellConstraint.firstItem attribute:cellConstraint.firstAttribute relatedBy:cellConstraint.relation toItem:contentView attribute:cellConstraint.secondAttribute multiplier:cellConstraint.multiplier constant:cellConstraint.constant];
            parallelConstraint.priority = cellConstraint.priority;
            [cell removeConstraint:cellConstraint];
            [contentView addConstraint:parallelConstraint];
        }
    }

    // restore auto-resizing mask to iOS 7 behavior
    contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [cell setNeedsUpdateConstraints];
    [cell updateConstraintsIfNeeded];
}
4
PlayfulGeek

Il s’agit d’un bogue de SDK xCode6 et iOS 8 fonctionnant sur des appareils iOS7:) Enfin, cela a fonctionné avec le code ci-dessous dans la sous-classe UICollectionViewCell. J'espère que cela sera corrigé avec la prochaine version

- (void)setBounds:(CGRect)bounds {
    [super setBounds:bounds];
    self.contentView.frame = bounds;
}
0
Krishna Kishore

J'ai eu le même problème pour UITableViewCells et iOS 7 (ios8 fonctionne parfaitement), mais la solution "Triet Luong" a fonctionné pour moi:

return [sampleCell.containerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
0
Davis

Ce n’est pas un bug, je suis aux prises avec ce problème depuis un certain temps et j’ai essayé différentes choses. Je donne ci-dessous les étapes qui ont fonctionné pour moi:

1) utilisez contentView [sampleCell.contentView systemLayoutSizeFittingSize: UILayoutFittingCompressedSize];

2) vous pouvez créer votre propre contentView et avoir les sous-vues ajoutées à la contentView, n'oubliez pas d'épingler le haut, le bas, la gauche et la droite du contentView si vous utilisez un contentView personnalisé sur le superView, sinon Pour ce faire, la hauteur sera 0, ici aussi en fonction de vos besoins. Par exemple, ne pas épingler le bas de contentView à superView afin que la hauteur de la vue puisse varier, mais épingler est important et déterminer lequel dépend de vos besoins.

3) définissez correctement les contraintes dans le générateur d'interface en fonction de vos besoins. Certaines contraintes ne peuvent pas être ajoutées dans le générateur d'interface, mais vous pouvez ensuite les ajouter dans viewDidLoad du viewController.

Donc, mon entrée de 2 centimes est que les contraintes doivent être définies correctement dans le générateur d'interface pour systemLayoutSizeFittingSize: UILayoutFittingCompressedSize pour renvoyer les dimensions correctes, il s'agit de la solution type.

0
Sam Paul

peut-être avez-vous une contrainte incorrecte, vous devez spécifier à la fois l'espace supérieur virtuel et l'espace inférieur entre votre UIView et contentView , j'avais également ce problème auparavant, car je venais de spécifier l'espace supérieur virtuel et je ne l'avais pas spécifié l'espace inférieur virtuel à contentView 

0
Gene