2015-10-27 15 views
6

Mam UIStackView zawarty wewnątrz UICollectionViewCell do reprezentowania post w sieci społecznej (podobny styl do komórek Instagram). Numer UIStackView zawiera nagłówek autora (niestandardowy UIView), UIImageView dla obrazu zawartości, UILabel dla treści posta i UIToolbar dla działań. Ostateczny widok wygląda na this.UIStackView błędnie oblicza wysokość UIImageView

Wysokość UICollectionViewCell jest ustawiany poprzez ustawienie się komórkę rozmiaru, tak jak poniżej:

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

} 

problemem jest to, że UIImageView wydaje się, że zwiększenie wielkości UICollectionViewCell, bez zwiększenie rozmiar widoku obrazu. This is the result, gdy dodaję duży obraz do widoku obrazu. Pożądanym rezultatem jest zachowanie proporcji obrazu 1: 1, ograniczonej do szerokości UIStackView.

Rozmiar luki między etykietą body a resztą treści zmienia się w zależności od używanego obrazu. To prowadzi mnie do przekonania, że ​​w pewnym stopniu rozmiar obrazu jest brany pod uwagę dla rozmiaru komórki tylko dlatego, że wizualnie widok obrazu ma prawidłowy rozmiar. Jak widać na pierwszym opublikowanym obrazie, komórka idealnie się prezentuje, gdy obraz obrazu nie został ustawiony.

Oto kod instalacyjny do widoku stosu, widzenia obrazu i etykiet:

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

Jakieś pomysły?

Odpowiedz

7

Ustaliliśmy to! Jak stwierdzono w dokumentach, UIStackView używa intrinsicContentSize swojego arrangedSubviews do obliczenia swojej wysokości.

UIImageView zgłasza swój intrinsicContentSize jako cały rozmiar obrazu (jak można się spodziewać). UIStackView ignorował moje ograniczenie wysokości i tylko przy użyciu intrinsicContentSize widoku obrazu.

Aby to naprawić, utworzyłem podklasę UIImageView, która umożliwia dzwoniącemu ustawienie intrinsicContentSize. Ten kod można znaleźć here.

Następnie w moim UICollectionViewCell ja ustawiania podklasy UIImageView intrinsicContentSize raz karnet układ zdobył:

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

Innym rozwiązaniem, jeśli nie chcesz, aby to zrobić programowo , jest użycie 2 UIStackViews w pionie. W górnym UIStackView, który zawiera UIImageView, ustaw jego ograniczenie wysokości do zajęcia, powiedzmy 70% wysokości superspirta, i pozwól dolnemu UIStackView usiąść tuż obok pierwszego, więc zajmie pozostałe 30% wysokości.

W ten sposób, niezależnie od tego, jak duży jest Twój obraz, zawsze zajmie to 70% wysokości.

Powiązane problemy