我在UICollectionViewCell中包含一个UIStackView来表示社交网络上的帖子(类似于Instagram的单元格). UIStackView包含一个作者标题(自定义UIView),一个用于内容图像的UI
ImageView,一个用于帖子主体的UILabel,以及一个用于操作的UIToolbar.最终视图看起来像
this.
通过设置大小调整单元来设置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的大小,而没有增加图像视图的大小. This is the result当我向图像视图添加大图像时.所需的结果是图像保持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,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使用其arrangeSubviews的intrinsicContentSize来计算其高度.
UIImageView将其intrinsicContentSize报告为图像的整个大小(正如您所期望的那样). UIStackView忽略了我的高度约束,只是使用了图像视图的intrinsicContentSize.
为了解决这个问题,我创建了一个UIImageView子类,允许调用者设置intrinsicContentSize.这段代码可以找到here.
然后,在我的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];
}