ios swift5 collectionView waterfall flow (two columns)

1. Waterfall

1.1 demo address

CollectionViewWaterfallLayout - github

Please add a picture description

1.2 Remember to change the minimum version of the deployment from 8 to 11, 13 or even higher. Otherwise, the compilation will report an error

Please add a picture description

2. Dynamically calculate the height of pictures and text

//可以正常使用
import UIKit
import SnapKit
class ConcernedVC: UICollectionViewController, UICollectionViewDelegateFlowLayout {
    
    

    let cellReuseIdentifier = "WaterfallCell"
    let itemsPerRow: CGFloat = 2
    let sectionInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
    let itemSpacing: CGFloat = 10 // Spacing between items in the same column
    var columnHeights: [CGFloat] = [0, 0] // Heights of the two columns

    let sampleData: [(image: UIImage, text: String)] = [
        (UIImage(named: "img_about us_app")!, "Sample Text 1"),
        (UIImage(named: "banner")!, "Sample Text 2adfahdfkajdfiahdofhadoifhaodhfaoihdfhasdifhaidhfapfdhiashf"),
        (UIImage(named: "img_about us_app")!, "Sample Text 1"),
        (UIImage(named: "banner")!, "Sample Text 2adfahdfkajdfiahdofhadoifhaodhfaoihdfhasdifhaidhfapfdhiashf"),
        (UIImage(named: "img_about us_app")!, "Sample Text 1"),
        (UIImage(named: "banner")!, "Sample Text 2adfahdfkajdfiahdofhadoifhaodhfaoihdfhasdifhaidhfapfdhiashf"),
        (UIImage(named: "img_about us_app")!, "Sample Text 1"),
        (UIImage(named: "img_about us_app")!, "Sample Text 1"),

        // Add more sample data here
    ]

    override func viewDidLoad() {
    
    
        super.viewDidLoad()
        
//        let layout = UICollectionViewFlowLayout() // Create a layout instance
//        collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) // Initialize UICollectionView with the layout
        

        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.register(WaterfallCell.self, forCellWithReuseIdentifier: cellReuseIdentifier)
        collectionView.backgroundColor = .white
    }

    // MARK: UICollectionViewDataSource

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    
    
        return sampleData.count
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
    
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellReuseIdentifier, for: indexPath) as! WaterfallCell
        let data = sampleData[indexPath.item]
        cell.configure(with: data)
        return cell
    }

    // MARK: UICollectionViewDelegateFlowLayout


    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    
    
        let paddingSpace = sectionInsets.left * (itemsPerRow + 1)
        let availableWidth = collectionView.frame.width - paddingSpace
        let widthPerItem = availableWidth / itemsPerRow
        let data = sampleData[indexPath.item]
        let imageAspectRatio = data.image.size.width / data.image.size.height
        let textHeight = data.text.height(withConstrainedWidth: widthPerItem - 16, font: UIFont.systemFont(ofSize: 14))
        let imageHeight = min(200, widthPerItem / imageAspectRatio) // Limit image height
        let totalHeight = imageHeight + textHeight + 16
        return CGSize(width: widthPerItem, height: totalHeight)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    
    
        return sectionInsets
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    
    
        return sectionInsets.left
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    
    
        return sectionInsets.left
    }
}
class WaterfallCell: UICollectionViewCell {
    
    
    let imageView = UIImageView()
    let label = UILabel()

    override init(frame: CGRect) {
    
    
        super.init(frame: frame)
        contentView.backgroundColor = .yellow
        contentView.addSubview(imageView)
        imageView.contentMode = .scaleAspectFill
        imageView.clipsToBounds = true

        contentView.addSubview(label)
        label.numberOfLines = 2
        label.font = UIFont.systemFont(ofSize: 14)
    }

    required init?(coder: NSCoder) {
    
    
        fatalError("init(coder:) has not been implemented")
    }

    func configure(with data: (image: UIImage, text: String)) {
    
    
        imageView.image = data.image
        label.text = data.text

        let imageAspectRatio = data.image.size.width / data.image.size.height
        let imageHeight = frame.width / imageAspectRatio
        imageView.frame = CGRect(x: 0, y: 0, width: frame.width, height: imageHeight)

        label.frame = CGRect(x: 0, y: imageHeight + 8, width: frame.width, height: labelHeight)
    }

    private var labelHeight: CGFloat {
    
    
        let labelWidth = frame.width - 16
        return label.text?.height(withConstrainedWidth: labelWidth, font: UIFont.systemFont(ofSize: 14)) ?? 0
    }
}
extension String {
    
    
    func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
    
    
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
        return ceil(boundingBox.height)
    }
}

//使用
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
let vc = ConcernedVC(collectionViewLayout: layout)

Guess you like

Origin blog.csdn.net/baidu_40537062/article/details/132287796