32 votes

UICollectionViewFlowLayout estimatedItemSize ne fonctionne pas correctement avec iOS12 alors qu'il fonctionne bien avec iOS 11.*.

Pour les cellules de hauteur dynamique de UICollectionView, nous utilisons,

if let layout = self.collectionViewLayout as? UICollectionViewFlowLayout {
    layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize
}

avec la contrainte appropriée de hauteur et de largeur, cela fonctionne bien avec les versions iOS 11.* mais cela casse et ne rend pas les cellules dynamiques pour iOS 12.0

67voto

ale84 Points 501

Dans mon cas, j'ai résolu ce problème en ajoutant explicitement les contraintes suivantes à la ContentView de la cellule.

class Cell: UICollectionViewCell {
    // ...

    override func awakeFromNib() {
        super.awakeFromNib()

        // Addresses a separate issue and prevent auto layout warnings due to the temporary width constraint in the xib.
        contentView.translatesAutoresizingMaskIntoConstraints = false

        // Code below is needed to make the self-sizing cell work when building for iOS 12 from Xcode 10.0:
        let leftConstraint = contentView.leftAnchor.constraint(equalTo: leftAnchor)
        let rightConstraint = contentView.rightAnchor.constraint(equalTo: rightAnchor)
        let topConstraint = contentView.topAnchor.constraint(equalTo: topAnchor)
        let bottomConstraint = contentView.bottomAnchor.constraint(equalTo: bottomAnchor)
        NSLayoutConstraint.activate([leftConstraint, rightConstraint, topConstraint, bottomConstraint])
    }
}

Ces contraintes sont déjà en place dans le xib de la cellule, mais d'une manière ou d'une autre, elles ne sont pas suffisantes pour iOS 12.

Les autres fils de discussion qui suggéraient d'appeler collectionView.collectionViewLayout.invalidateLayout() à divers endroits n'a pas aidé dans ma situation.

Exemple de code ici : https://github.com/larrylegend/CollectionViewAutoSizingTest

Ceci applique la solution de contournement au code d'un tutoriel de https://medium.com/@wasinwiwongsak/uicollectionview-with-autosizing-cell-using-autolayout-in-ios-9-10-84ab5cdf35a2 :

8voto

Vasil Garov Points 2455

Sur la base de ale84 En raison de la réponse de l'entreprise et du fait que j'avais besoin de la correction iOS 12 à plusieurs endroits, j'ai créé une extension UICollectionViewCell que j'ai nommée UICollectionViewCell+iOS12 :

extension UICollectionViewCell {
    /// This is a workaround method for self sizing collection view cells which stopped working for iOS 12
    func setupSelfSizingForiOS12(contentView: UIView) {
        contentView.translatesAutoresizingMaskIntoConstraints = false
        let leftConstraint = contentView.leftAnchor.constraint(equalTo: leftAnchor)
        let rightConstraint = contentView.rightAnchor.constraint(equalTo: rightAnchor)
        let topConstraint = contentView.topAnchor.constraint(equalTo: topAnchor)
        let bottomConstraint = contentView.bottomAnchor.constraint(equalTo: bottomAnchor)
        NSLayoutConstraint.activate([leftConstraint, rightConstraint, topConstraint, bottomConstraint])
    }
}

Ensuite, dans les cellules de votre vue de collection, nous faisons quelque chose comme ceci (si votre cellule est créée dans IB) :

override func awakeFromNib() {
    super.awakeFromNib()
    if #available(iOS 12, *) { setupSelfSizingForiOS12(contentView: contentView) }
}

1voto

Harish Pathak Points 956

Version Objective C de la réponse ci-dessus :

-(void)awakeFromNib{
    [super awakeFromNib];

    if (@available(iOS 12.0, *)) {
        // Addresses a separate issue and prevent auto layout warnings due to the temporary width constraint in the xib.
        self.contentView.translatesAutoresizingMaskIntoConstraints = NO;

        // Code below is needed to make the self-sizing cell work when building for iOS 12 from Xcode 10.0:

        NSLayoutConstraint *leftConstraint = [self.contentView.leftAnchor constraintEqualToAnchor:self.leftAnchor constant:0];
        NSLayoutConstraint *rightConstraint = [self.contentView.rightAnchor constraintEqualToAnchor:self.rightAnchor constant:0];
        NSLayoutConstraint *topConstraint = [self.contentView.topAnchor constraintEqualToAnchor:self.topAnchor constant:0];
        NSLayoutConstraint *bottomConstraint = [self.contentView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:0];

        [NSLayoutConstraint activateConstraints:@[leftConstraint, rightConstraint, topConstraint, bottomConstraint]];
    }

}

Pour les amoureux de l'Objective-C comme moi ;) santé ! !!

-1voto

CDM Points 255

J'ai le même problème, car j'utilise UILabels pour dimensionner la vue de la collection. collectionView.collectionViewLayout.invalidateLayout() avant de recharger les données, il fait un travail correct de dimensionnement des étiquettes.

C'est difficile pour moi de comprendre parce que je l'exécute sur le simulateur plutôt que sur le dispositif.

-1voto

user1531233 Points 1

J'ai réussi à résoudre ce problème en plaçant ce code dans ma sous-classe de UICollectionViewCell.

- (UICollectionViewLayoutAttributes *)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
    [self updateConstraintsIfNeeded];
    CGSize size = [self systemLayoutSizeFittingSize:CGSizeMake(1000, 1000)];

    CGRect alteredRect = layoutAttributes.frame;
    alteredRect.size = size;
    layoutAttributes.frame = alteredRect;
    return layoutAttributes;
}

et en sous-classant UICollectionView comme ceci

@interface CustomCollectionView ()
@property (nonatomic) BOOL shouldInvalidateLayout;
@end

@implementation CustomCollectionView

- (void)layoutSubviews {
    [super layoutSubviews];
    if (self.shouldInvalidateLayout) {
        [self.collectionViewLayout invalidateLayout];
        self.shouldInvalidateLayout = NO;
    }
}

- (void)reloadData {
    self.shouldInvalidateLayout = YES;
    [super reloadData];
}

@end

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