2015-10-27 5 views
6

Ich habe eine UIStackView enthalten in einer UICollectionViewCell, um einen Beitrag in einem sozialen Netzwerk (ähnlich wie Instagram-Zellen) darzustellen. Die UIStackView enthält eine Autorenkopfzeile (benutzerdefiniert UIView), eine UIImageView für das Inhaltsbild, eine UILabel für den Post-Körper und eine UIToolbar für die Aktionen. Die endgültige Ansicht sieht wie folgt aus: this.UIStackView miscalculating UIImageView Höhe

Die Höhe des UICollectionViewCell wird durch die Einrichtung einer Schlichtzelle gesetzt wird, etwa so:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { 
     NTVFeedBlogCollectionViewCell *cell = [[NTVFeedBlogCollectionViewCell alloc] initWithFrame:CGRectMake(10.0f, 0.0f, collectionView.frame.size.width - 20.0f, 900000.0)]; 

     // ... 
     // Configure the cell 
     // ... 

     [cell setNeedsLayout]; 
     [cell layoutIfNeeded]; 
     CGSize size = [cell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; 

     return CGSizeMake(CGRectGetWidth(collectionView.frame) - 20.0f, size.height); 

} 

Das Problem ist, dass die UIImageView Erhöhung der Größe des UICollectionViewCell die ohne scheint zuzunehmen Größe der Bildansicht. This is the result wenn ich der Bildansicht ein großes Bild hinzufüge. Das gewünschte Ergebnis ist, dass das Bild ein Seitenverhältnis von 1: 1 beibehält, das auf die Breite des UIStackView beschränkt ist.

Die Größe der Lücke zwischen dem Body Label und dem Rest des Inhalts ändert sich je nachdem, welches Bild ich verwende. Dies führt mich zu der Annahme, dass UIStackView irgendwie die Bildgröße für die Dimensionierung der Zelle nur berücksichtigt, da visuell die Bildansicht die richtige Größe ist. Wie Sie im ersten Bild gesehen haben, ist die Zelle perfekt ausgerichtet, wenn das Bildbild der Bildansicht nicht eingestellt wurde.

Hier ist der Setup-Code für die Stapelansicht, Bildansicht und Labels:

self.stackView = [[UIStackView alloc] initWithFrame:CGRectZero]; 
self.stackView.translatesAutoresizingMaskIntoConstraints = NO; 
self.stackView.axis = UILayoutConstraintAxisVertical; 
self.stackView.distribution = UIStackViewDistributionFill; 
self.stackView.alignment = UIStackViewAlignmentFill; 
self.stackView.spacing = 10.0f; 
self.stackView.layoutMargins = UIEdgeInsetsMake(10.0f, 10.0f, 0.0f, 10.0f); 
self.stackView.layoutMarginsRelativeArrangement = YES; 

[self addSubview:self.stackView]; 

[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[stackView]-0-|" 
                  options:0 
                  metrics:nil 
                   views:@{@"stackView": self.stackView}]]; 

[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[stackView]-0-|" 
                  options:0 
                  metrics:nil 
                   views:@{@"stackView": self.stackView}]]; 

self.imageView = [[UIImageView alloc] initWithFrame:CGRectZero]; 

[self.imageView setImage:[UIImage imageNamed:@"sample_image.png"]]; 

self.imageView.translatesAutoresizingMaskIntoConstraints = NO; 
self.imageView.contentMode = UIViewContentModeScaleAspectFill; 
self.imageView.clipsToBounds = YES; 
self.imageView.layer.masksToBounds = YES; 
self.imageView.backgroundColor = [UIColor greenColor]; 

[self.imageView setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical]; 
[self.imageView setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisVertical]; 

[self.stackView addArrangedSubview:self.imageView]; 

[self.stackView addConstraint:[NSLayoutConstraint constraintWithItem:self.imageView 
                  attribute:NSLayoutAttributeHeight 
                  relatedBy:NSLayoutRelationEqual 
                   toItem:self.stackView 
                  attribute:NSLayoutAttributeWidth 
                  multiplier:1.0f 
                  constant:0.0f]]; 

self.bodyLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 
[self.bodyLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical]; 
[self.bodyLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisVertical]; 
self.bodyLabel.font = [UIFont ntv_lightFontWithSize:17.0f]; 
self.bodyLabel.textColor = [UIColor whiteColor]; 
self.bodyLabel.numberOfLines = 0; 

self.bodyLabel.text = @"While the stack view allows you to layout its contents without using Auto Layout directly, you still need to use Auto Layout to position the stack view, itself."; 
[self.stackView addArrangedSubview:self.bodyLabel]; 

self.accessoryView = [[NTVAccessoryView alloc] initWithFrame:CGRectZero]; 
self.accessoryView.viewModel = [NTVAccessoryManagerViewModel_Stubbed new]; 

[self.stackView addArrangedSubview:self.accessoryView]; 

Irgendwelche Ideen?

Antwort

7

Wir haben es herausgefunden! Wie in den Dokumenten angegeben, verwendet die UIStackView die intrinsicContentSize ihrer arrangedSubviews, um ihre Höhe zu berechnen.

UIImageView meldet seine intrinsicContentSize als die gesamte Größe des Bildes (wie Sie erwarten würden). UIStackView ignorierte meine Höhenbeschränkung und nur mit der intrinsicContentSize der Bildansicht.

Um das zu beheben, habe ich eine UIImageView Unterklasse erstellt, die es einem Anrufer ermöglicht, die intrinsicContentSize festzulegen. Dieser Code kann here gefunden werden.

Dann in meinem UICollectionViewCell Ich gründe die UIImageView Unterklasse intrinsicContentSize einmal das Layout Pass abgeschlossen hat:

- (void)layoutSubviews { 
    [super layoutSubviews]; 

    // Constrain the image view's content size to match the stackview's width. 
    self.imageView.constrainedSize = CGSizeMake(self.stackView.frame.size.width, self.stackView.frame.size.width); 

    [super layoutSubviews]; 

}

0

Die andere Lösung, wenn Sie es programmatisch nicht tun wollen , verwenden Sie 2 UIStackViews vertikal. Das oberste UIStackView, das UIImageView enthält, setzt seine Höhenbeschränkung auf etwa 70% der Höhe der Superview und lässt das untere UIStackView direkt neben dem obersten stehen, so dass die verbleibenden 30% der Höhe benötigt werden.

Auf diese Weise, egal wie groß Ihr Bild ist, wird es immer 70% der Höhe nehmen.