webentwicklung-frage-antwort-db.com.de

Wie kann man die automatische Layoutgröße der UICollectionViewCells in iOS 8 ermitteln? (systemLayoutSizeFittingSize gibt in iOS 8 eine Größe mit Nullhöhe zurück)

Seit iOS 8 gibt [UIColletionViewCell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] eine Größe mit der Höhe 0 zurück. 

So funktioniert der Code:

Um die Größe einer Zelle in einer UICollectionView in iOS 7 zu bestimmen, verwende ich systemLayoutSizeFittingSize: in einer Zelle, die in einer Xib-Datei mit Auto Layout definiert ist. Die Größe hängt von der Schriftgröße einer UILabel ab, die eine Unteransicht der UICollectionViewCell in meiner Xib-Datei ist. Die Schriftart des Labels ist auf UIFontTextStyleBody gesetzt. Grundsätzlich hängt die Größe der Zelle von der in iOS 7 vorgenommenen Einstellung der Schriftgröße ab. 

Hier ist der Code selbst:

+ (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;

}

Es funktioniert perfekt in iOS 7, aber nicht in iOS 8. Leider habe ich keine Ahnung, warum. 

Wie kann ich die automatische Layoutgröße der UICollectionViewCells in iOS 8 ermitteln?

PS: Verwenden von 

 return [sampleCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

anstatt

 return [sampleCell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

wie jemand vermuten könnte, macht das keinen Unterschied. 

25
martn_st

Sieht offiziell so aus: Ich habe einen Bericht eingereicht, der als Duplikat von dieser geschlossen wurde

Werde zurückmelden, wenn Beta 6 raus ist.

[ Update : Funktioniert ordnungsgemäß im GM Seed von iOS 8 und der Fehler wurde von Apple geschlossen.]

7

Was Sie tun müssen, ist den gesamten Inhalt in eine Containeransicht zu packen und dann aufzurufen:

return [sampleCell.containerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

Ihre Zelle sollte folgendermaßen aussehen: cell -> containerView -> sub views

Dies funktioniert sowohl für ios7 als auch für ios8. 

Bei ios8 müssen Sie lediglich festlegen, dass die Größe und die Größe des Schätzwerts automatisch angepasst werden. Anscheinend funktioniert das ab Beta 6 nicht. 

8
Triet Luong

Wir verwenden jetzt eine Umgehungslösung, die unten kopiert ist. Hoffentlich werden diese Probleme vor der Veröffentlichung von iOS 8 behoben, und wir können das Problem beheben. (Der Kludge setzt Kenntnisse des impliziten Verhaltens von Apple in Bezug auf ViewView voraus, und wir müssen IB-Outlet-Verweise auf die von uns übertragenen Einschränkungen hacken.)

Es fällt auf, dass beim Aktualisieren auch alle autoresizingMasks aus Storyboards/NIBs entfernt werden. Dies ist sinnvoll, wenn es sich um ein automatisches Layout handelt. Die Sammlungsansichten wirken sich jedoch nach wie vor auf Federn und Streben aus. Vielleicht wurde dies bei der Säuberung übersehen?

--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

Dies ist ein Fehler in xCode6 und iOS 8 SDK, der auf iOS7-Geräten ausgeführt wird:) Schließlich arbeitete es mit dem folgenden Code in der UICollectionViewCell-Unterklasse. Ich hoffe das wird mit der nächsten Version behoben

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

Ich hatte das gleiche Problem für UITableViewCells und iOS 7 (ios8 funktioniert perfekt), aber die Lösung "Triet Luong" funktionierte für mich:

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

Dies ist kein Fehler, ich habe mich seit einiger Zeit mit diesem Thema auseinandergesetzt und habe verschiedene Dinge ausprobiert. Ich gebe unter den Schritten, die für mich funktioniert haben:

1) verwenden Sie contentView [sampleCell.contentView systemLayoutSizeFittingSize: UILayoutFittingCompressedSize];

2) Sie können Ihr eigenes contentView erstellen und die SubViews zum contentView hinzufügen. Vergessen Sie nicht, den oberen, unteren, linken und rechten Rand des contentView zu fixieren, wenn Sie ein benutzerdefiniertes contentView mit dem superView verwenden, falls Sie dies nicht tun Wenn Sie dies tun, wird die Höhe 0 sein. Hier können Sie auch abhängig von Ihren Anforderungen wählen. Fügen Sie beispielsweise den unteren Teil des contentView nicht an das SuperView an, sodass die Höhe der Ansicht variieren kann. Das Pinnen ist jedoch wichtig. Das Pinning hängt von Ihren Anforderungen ab.

3) Legen Sie die Einschränkungen im Interface Builder je nach Ihren Anforderungen richtig fest. Es gibt bestimmte Einschränkungen, die nicht im Interface Builder hinzugefügt werden können. Sie können sie jedoch in viewDidLoad des viewControllers hinzufügen.

Meine 2-Cent-Eingabe ist also, dass die Einschränkungen im Interface Builder für systemLayoutSizeFittingSize: UILayoutFittingCompressedSize richtig festgelegt werden müssen, um korrekte Dimensionen zurückzugeben. Dies ist die Lösung.

0
Sam Paul

vielleicht haben Sie eine falsche Einschränkung, Sie sollten sowohl den virtuellen oberen als auch den unteren Raum zwischen UIView und contentView angeben. Ich hatte auch dieses Problem, weil ich nur den virtuellen oberen Platz angegeben und nicht angegeben habe der virtuelle untere Raum zu contentView 

0
Gene