【问题标题】:How to make horizontal CollectionView size fit its content programatically如何以编程方式使水平 CollectionView 大小适合其内容
【发布时间】:2023-01-17 05:22:42
【问题描述】:

我有一个占据整个屏幕的集合视图,应该水平滚动。

问题是我无法在保留轮播效果的同时调整项目的大小。如果我降低项目的大小,单元格垂直堆叠就像这里一样:

粉色背景是collectionView。 collectionView 填充视图控制器的视图,这就是单元格不水平对齐的原因。

对齐应该像这样水平滚动,就像旋转木马一样,但问题是它太大了,占据了整个视图。

单元格和集合视图的预期高度仅为 100 或 200 左右,并且仍然可以水平滚动。

这是我现有的代码:

我正在使用 SnapKit 进行约束。

视图控制器

import UIKit
import SnapKit

class ViewController: UIViewController {
    
    
    let viewModel: [SeatViewModel] = [.init(text: "single text"), .init(text: "slightly longer text."), .init(text: "very very very very long long text")]
    
    private lazy var collectionView: UICollectionView = {
      let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
      let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
      cv.delegate = self
      cv.backgroundColor = .white
      cv.register(SeatCardCell.self, forCellWithReuseIdentifier: "SeatCardCell")
      return cv
    }()


    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(collectionView)
        
        collectionView.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.width.equalTo(200)
            make.height.equalTo(100)
        }
        collectionView.dataSource = self
        collectionView.backgroundColor = .systemPink
    }
    

    
    func lines(label: UILabel) -> Int {
        self.collectionView.layoutIfNeeded()
        let textSize = CGSize(width: label.frame.size.width, height: CGFloat(Float.infinity))
        let rHeight = lroundf(Float(label.sizeThatFits(textSize).height))
        let charSize = lroundf(Float(label.font.lineHeight))
        let lineCount = rHeight/charSize
        return lineCount
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        collectionView.frame = view.bounds
    }
    
}

extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 3
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let collectioCell = collectionView.dequeueReusableCell(withReuseIdentifier: "SeatCardCell", for: indexPath) as? SeatCardCell else { fatalError() }
        collectioCell.backgroundColor = [UIColor.green, .red, .black, .brown, .yellow].randomElement()
        collectioCell.viewModel = viewModel[indexPath.row]
        return collectioCell
    }
    
}


extension ViewController: UICollectionViewDelegateFlowLayout {
        func collectionView(_ collectionView: UICollectionView,
                            layout collectionViewLayout: UICollectionViewLayout,
                            sizeForItemAt indexPath: IndexPath) -> CGSize {

            return CGSize(width: 200, height: self.collectionView.frame.height)
        }

        func collectionView(_ collectionView: UICollectionView,
                            layout collectionViewLayout: UICollectionViewLayout,
                            minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
            return 1.0
        }

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

查看模型和单元格

import UIKit
import SnapKit

struct SeatViewModel {
    let text: String
}

class SeatCardCell: UICollectionViewCell {
    
    var viewModel: SeatViewModel? {
        didSet {
            configure()
        }
    }

    // MARK: - Properties

    let seatImageView = UIImageView(image: nil)
    
    let seatLabel: CustomLabel = {
        let label = CustomLabel()
        return label
    }()

    // MARK: - Lifecycle

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

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

    
    private func configure() {
        guard let viewModel = viewModel else { return }
        seatLabel.text = viewModel.text
        seatLabel.backgroundColor = .cyan
        seatLabel.sizeToFit()
        seatImageView.image = .strokedCheckmark
        
        let stackView = UIStackView(arrangedSubviews: [seatImageView, seatLabel])
        stackView.spacing = 0
        stackView.alignment = .center
        
        addSubview(stackView)
        
        seatImageView.snp.makeConstraints { make in
            make.size.equalTo(40)
        }
        
        stackView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
    }
}


// MARK: - CUSTOM TITLE LABEL
class CustomLabel: UILabel {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    
    required init(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupUI() {
        self.textColor = .darkGray
        self.textAlignment = .left
        self.numberOfLines = 4
    }
}

【问题讨论】:

    标签: ios swift uicollectionview uikit


    【解决方案1】:

    您的代码的问题是您再次将集合视图框架设置为等于 viewDidLayoutSubviews 中的视图框架。

    您只需要删除它,您的代码就可以完美运行。

    override func viewDidLayoutSubviews() {
         super.viewDidLayoutSubviews()
         // remove it
         //collectionView.frame = view.bounds
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-17
      • 1970-01-01
      • 2011-02-26
      • 1970-01-01
      相关资源
      最近更新 更多