使用 Autolayout 和 UICollectionViewCompositionalLayout 的动态集合视图单元格中的 UIImage 大小调整

UIImage Sizing in Dynamic Collection View Cell with Autolayout and UICollectionViewCompositionalLayout

提问人:robinyapockets 提问时间:8/2/2023 更新时间:8/3/2023 访问量:26

问:

上下文:我有一个集合视图,其动态单元格高度由其单元格的内容定义。单元格的内容:UIView、UILabel 和 UIImage(图像和标签垂直放置)。

问题:当我将图像contentMode设置为scaleAspectFill时,自动布局似乎可以正常工作并相应地调整单元格的大小。但是,这会裁剪图像的侧面。当我将 contentMode 设置为 scaleAspectFit 时,它会在水平方向上正确调整图像大小,但保持以前的高度。

附上结果的图像。感谢您的任何提示和支持!

set to scaleToFill

set to scaleToFit

集合视图布局代码:

func createLayout() -> UICollectionViewLayout {
    let _: CGFloat = (self.view.frame.width*1.33) + 50
    let estimatedHeight = CGFloat(100)
    let layoutSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
                                           heightDimension: .estimated(estimatedHeight))
    
    
    let item = NSCollectionLayoutItem(layoutSize: layoutSize)
    
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: layoutSize,
                                                   repeatingSubitem: item,
                                                   count: 1)
    let section = NSCollectionLayoutSection(group: group)
    section.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10)
    section.interGroupSpacing = 10
    let layout = UICollectionViewCompositionalLayout(section: section)
    return layout
}

对于小区注册:

    let newCell = UICollectionView.CellRegistration<CustomCell, Asset> {(cell, indexPath, item) in
        let image = UIImage(named: "test")
        cell.label.text = "No comments"
        cell.imageView.image = image
    }

对于自定义单元格:

class CustomGroupItemCell: UICollectionViewCell {

    let container = UIView()
    let imageView = UIImageView()
    let label = UILabel()
        
    override init(frame: CGRect) {
        super.init(frame: frame)
        configure()
    }

    required init?(coder: NSCoder) {
       fatalError("not implemnted")
    } 

func configure() {
    container.translatesAutoresizingMaskIntoConstraints = false
    imageView.translatesAutoresizingMaskIntoConstraints = false
    label.translatesAutoresizingMaskIntoConstraints = false
    
    label.adjustsFontForContentSizeCategory = true
    label.numberOfLines = 0
    label.font = UIFont.systemFont(ofSize: 17, weight: .semibold)
    label.textColor = .label

    container.backgroundColor = .secondarySystemFill
    container.layer.cornerRadius = 12
    
    imageView.layer.cornerRadius = 5
    imageView.contentMode = .scaleAspectFill
    imageView.layer.masksToBounds = true

    contentView.addSubview(container)
    contentView.addSubview(label)
    contentView.addSubview(imageView)
    
    let views = [ "label": label, "container": container, "image": imageView]
    var constraints = [NSLayoutConstraint]()
    
    // Horizontal
    constraints.append(contentsOf: NSLayoutConstraint.constraints(
        withVisualFormat: "H:|[container]|", options: [], metrics: nil, views: views))
    constraints.append(contentsOf: NSLayoutConstraint.constraints(
        withVisualFormat: "H:|-20-[image]-20-|", options: [], metrics: nil, views: views))
    constraints.append(contentsOf: NSLayoutConstraint.constraints(
        withVisualFormat: "H:|-20-[label]-20-|", options: [], metrics: nil, views: views))
  
    // Vertical
    constraints.append(contentsOf: NSLayoutConstraint.constraints(
        withVisualFormat: "V:|[container]|",
        options: [], metrics: nil, views: views))
    constraints.append(contentsOf: NSLayoutConstraint.constraints(
        withVisualFormat: "V:|-20-[image]-20-[label]-24-|",
        options: [], metrics: nil, views: views))
    
    NSLayoutConstraint.activate(constraints)
}
}
Swift 自动布局 UIImageView UIChationViewCell

评论


答:

0赞 matt 8/3/2023 #1

你不能以任何自动魔法的方式做到这一点。当图像准备好放置在单元格中时,您需要读取其大小并相应地调整图像视图的大小约束。

例如,在我的应用程序中,图像视图和单元格宽度是固定的。当图像到达时,我计算出它的纵横比,并将该值设置为图像视图纵横比约束的乘数,从而设置高度以适合图像。

评论

0赞 robinyapockets 8/3/2023
谢谢@matt!我假设使用 iOS 15 的 UICollectionViewCompositionalLayout 可以在不使用 Autolayout 计算比率的情况下完成。对我来说,这感觉有点“骇人听闻”。将尝试计算比率和调整高度。
0赞 robinyapockets 8/3/2023
@matt的答案奏效了!对于任何感兴趣的人,这里有代码: func adjustImageHeight(for image: UIImage){ let ratio = image.size.height/image.size.width NSLayoutConstraint.activate([ imageView.heightAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: ratio, constant: -40) ]) } var image: UIImage?{ didSet{ adjustImageHeight(for: image!) } }