ios swift5 collectionView 瀑布流(两列)

文章目录

  • 1.瀑布流
    • [1.1 demo地址](#1.1 demo地址)
    • [1.2 记得把部署的最低版本由8改成11,13甚至更高。不然编译会报错](#1.2 记得把部署的最低版本由8改成11,13甚至更高。不然编译会报错)
  • 2.动态计算图片和文字的高度

1.瀑布流

1.1 demo地址

CollectionViewWaterfallLayout - github

1.2 记得把部署的最低版本由8改成11,13甚至更高。不然编译会报错

2.动态计算图片和文字的高度

swift 复制代码
//可以正常使用
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)
相关推荐
黑化旺仔11 小时前
【OC】KVO
macos·ios·objective-c·cocoa
HouWan13 小时前
SwiftUI 小技巧:如何读取 SwiftUI Font 的详细信息
ios·swiftui·apple
李游Leo13 小时前
HarmonyOS 7 实战开发 05:把页面做到可上线状态
ios·harmonyos
终端安全笔记18 小时前
描述文件、企业证书、MDM 不是三个名字,是三层
android·ios·智能手机
传奇开心果编程19 小时前
【SwiftUI入门练中学】第1课 从零开始
学习·ui·ios·swiftui·swift
丿Wayne1 天前
iOS Token 刷新实战(Actor 避免并发重复刷新)
ios·swift·token·actor·swift并发
终端安全笔记2 天前
iOS 27 给了租赁一个新工具,但它只认受监督的设备
android·网络·安全·ios
大熊猫侯佩2 天前
独立 App 首发完成 iPhone Duo 展开态适配
ios·swiftui·swift
光影少年2 天前
setImmediate 和 setTimeout(0) 的区别
android·前端·react.js·ios·前端框架
2501_916008892 天前
SSE 和 gRPC 流式接口如何抓包,调试 SSE 与 gRPC 流式接口
网络协议·计算机网络·网络安全·ios·adb·https·udp