ios -基于纵横比动态调整图像大小的合成布局?

cwdobuhd  于 2023-02-06  发布在  iOS
关注(0)|答案(1)|浏览(158)

我正在尝试将合成布局与UICollectionView一起使用,其中每个单元格都包含一个具有动态纵横比的图像。我正在对单元格使用自动布局,但无法正确地自动调整单元格的大小。

指定单元格布局/约束的正确方法是什么,以便它们具有基于图像纵横比的正确高度?

在下面的代码中,图像本身的大小是正确的,但是包含它们的单元格没有正确的高度(它们只是使用估计的高度,而不是根据包含的图像动态调整)。
(我知道使用UICollectionViewFlowLayout相对简单,但我正在尝试学习组合布局,使用此方法还不能弄清楚)

下面是我在代码中设置的内容:

为了简化这篇文章,我使用了一个基本的组合布局,其中包含1个组和1个项,并使用heightDimension: .estimated(300)作为占位符

let layout = UICollectionViewCompositionalLayout { (sectionIndex, layoutEnvironment) -> NSCollectionLayoutSection? in

            let item = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(300)))
            
            let group = NSCollectionLayoutGroup.vertical(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(300)), subitem: item, count: 1)
            
            let section = NSCollectionLayoutSection(group: group)
            
            return section
}
collectionView.setCollectionViewLayout(layout, animated: false)

下面是该单元格的代码:

// during cellForItemAt, I call 
// cell.setImage(url: [url from API], size: [dynamic value from API])

class ImageCell: UICollectionViewCell {
    
    static let ImageCellIdentifier = String(describing: ImageCell.self)
    
    var aspectRatioConstraint: NSLayoutConstraint?
    
    private let imageView: UIImageView = {
        let imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.contentMode = .scaleAspectFill
        return imageView
    }()
    
    func setImage(url: URL, size: CGSize) {
        
        let aspectRatio = size.width / size.height
        
        if let aspectRatioConstraint = aspectRatioConstraint {
            imageView.removeConstraint(aspectRatioConstraint)
        }
        
        // set the image height constraint based on its aspect ratio
        // anchor it to contentView.widthAnchor
        aspectRatioConstraint = imageView.heightAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: aspectRatio)
        
        NSLayoutConstraint.activate([
            aspectRatioConstraint!,
        ])
        
        imageView.sd_setImage(with: url)
        
        contentView.layoutIfNeeded()

    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        contentView.addSubview(imageView)
        
        NSLayoutConstraint.activate([
            imageView.topAnchor.constraint(equalTo: contentView.topAnchor),
            imageView.widthAnchor.constraint(equalTo: contentView.widthAnchor),
        ])
        
    }
}

jgovgodb

jgovgodb1#

感谢@DonMag的评论,答案是每个项目创建一个部分,并相应地指定每个项目部分的布局:
假设images填充有动态图像列表(例如,来自API)

func numberOfSections(in collectionView: UICollectionView) -> Int {
  return images.count
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  return 1 // return more if you want to render additional kinds of cell for each item besides the image
}

组合布局的设置如下所示--重要的部分是... heightDimension: .fractionalWidth(aspectRatio)

let layout = UICollectionViewCompositionalLayout { (sectionIndex, layoutEnvironment) -> NSCollectionLayoutSection? in
    
    // use sectionIndex as an index into the list retrieved from API
        
    let image = images[sectionIndex]
    
    let aspectRatio = image.width / image.height
    
    let item = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(aspectRatio)))
    
    let group = NSCollectionLayoutGroup.vertical(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(aspectRatio)), subitem: item, count: 1)
    
    let section = NSCollectionLayoutSection(group: group)
    
    return section
}

collectionView.setCollectionViewLayout(layout, animated: false)

谢谢@DonMag!

相关问题