首页 > 解决方案 > 根据图像制作具有 UIImageView 高度的 UICollectionViewCells

问题描述

我想UICollectionView用单元格制作屏幕的宽度,但高度基于UIImageView内部的纵横比。

在我当前的实现中,所有UICollectionViewCell实例都是正方形,这不是我想要的。

我想以某种方式使用自动布局来使图像的大小成为屏幕的宽度,但相关的高度取决于所用图像的纵横比。

一切都是在代码中以编程方式完成的。

在此处输入图像描述

我的代码:

class ViewController: UIViewController {
    var data = ["1","2","3","4","5","6","7","8","1","2","3","4","5","6","7","8"]

    var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()
        self.collectionView.dataSource = self
        self.collectionView.delegate = self
        self.collectionView.register(SubclassedCollectionViewCell.self, forCellWithReuseIdentifier: "cell")
        self.collectionView.alwaysBounceVertical = true
        self.collectionView.backgroundColor = .white
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
    }

    override func loadView() {
        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        layout.itemSize = CGSize(width: UIScreen.main.bounds.size.width - 20, height: UIScreen.main.bounds.size.width / 1)
        layout.scrollDirection = .vertical
        collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        self.view = collectionView
    }
}

extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        data.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? SubclassedCollectionViewCell {
            let data = self.data[indexPath.item]
            cell.setupCell(image: data)
            return cell
        }
        fatalError("Could not dequeue cell")
    }
}

与细胞

class SubclassedCollectionViewCell: UICollectionViewCell {
    var hotelImageView: UIImageView = {
        var hotelView = UIImageView()
        hotelView.contentMode = .scaleAspectFill
        hotelView.clipsToBounds = true
        return hotelView
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        addSubview(hotelImageView)
        hotelImageView.translatesAutoresizingMaskIntoConstraints = false
        hotelImageView.topAnchor.constraint(equalTo: topAnchor).isActive = true
        hotelImageView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
        hotelImageView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
        hotelImageView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func setupCell(image: String) {
        if let image : UIImage = UIImage(named: image) {
            hotelImageView.image = image
        }
    }
}

标签: swiftuicollectionview

解决方案


首先,根据宽度计算比率并乘以集合视图宽度,您可以获得基于宽度的新高度。

最终代码:从 loadview 函数中删除 itemSize。并在 sizeForItemAt 方法中计算高度和返回项目大小。

加载视图

override func loadView() {
    let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
//        layout.itemSize = CGSize(width: UIScreen.main.bounds.size.width - 20, height: UIScreen.main.bounds.size.width / 1) <-- Remove this
    layout.scrollDirection = .vertical
    collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
    self.view = collectionView
}

UICollectionViewDelegateFlowLayout

extension ViewController: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        data.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? SubclassedCollectionViewCell {
            let data = self.data[indexPath.item]
            cell.setupCell(image: data)
            return cell
        }
        fatalError("Could not dequeue cell")
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        guard let iamgeData = UIImage(named: self.data[indexPath.item]) else {
            return .zero
        }
        let width = collectionView.bounds.width
        let heightOnWidthRatio = iamgeData.size.height / iamgeData.size.width
        let height = width * heightOnWidthRatio
        
        return CGSize(width: width, height: height)
    }
}

在此处输入图像描述


推荐阅读