Kir*_*sar 7 objective-c uiimageview ios autolayout uistackview
我有一个UIStackView包含UICollectionViewCell在一个社交网络上的帖子(类似于Instagram的单元格).它UIStackView包含一个作者标题(自定义UIView),一个UIImageView用于内容图像,一个UILabel用于帖子正文,一个UIToolbar用于操作.最终视图看起来像这样.
通过设置大小调整单元来设置UICollectionViewCell的高度,如下所示:
- (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);
}
问题是UIImageView似乎增加了UICollectionViewCell 的大小,而没有增加图像视图的大小.这是我向图像视图添加大图像时的结果.所需的结果是图像保持1:1的宽高比,受限于UIStackView的宽度.
身体标签与其余内容之间的间隙大小根据我使用的图像而变化.这使我相信,仅仅UIStackView考虑到图像大小,仅考虑细胞的大小,因为在视觉上图像视图是正确的大小.正如您在第一张贴图中看到的那样,当图像视图的图像尚未设置时,单元格完美展现.
以下是堆栈视图,图像视图和标签的设置代码:
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];
有任何想法吗?
我们想通了!正如文档中所述,UIStackView正在使用intrinsicContentSize它arrangedSubviews来计算它的高度.
UIImageView报告它intrinsicContentSize作为图像的整体大小(正如您所期望的那样).UIStackView忽略了我的身高限制,只是使用intrinsicContentSize了图像视图.
为了解决这个问题,我创建了一个UIImageView子类,允许调用者设置intrinsicContentSize.这段代码可以在这里找到.
然后,在我的布局传递完成后,UICollectionViewCell我正在设置UIImageView子类intrinsicContentSize:
- (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];
}