为什么collectionView-cell突然变大了?

时间:2019-05-23 19:25:27

标签: swift cell viewcontroller collectionview

使用swift-5.0.1,iOS-12.2和

我在UICollectionView上观察到一个奇怪的行为:

有些屏幕范围的单元格在我的collectionView中显示图像。

我的观察是,每当无法获取图像时,上述单元格的大小就会比预期的大。问题是为什么??

下图说明了该问题:

enter image description here

任何无法获取的图像显然无法显示,并且其单元格的backgroundColer等于红色。所有这一切。但是,为什么在nil-cell上方的一个单元格的大小增加了??

所有单元格的大小应由黄色框指示。

我在代码中有两个地方可以触摸单元格的高度:

  1. 在UICollectionViewCell初始化程序内部:

mainImageView.heightAnchor.constraint(equalToConstant: 150)

  1. 在UICollectionViewController sizeForItemAt内部:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return .init(width: view.frame.width, height: 150)
    }

两者都设置为150!但是在错误情况下,大单元格大于150-为什么??

这是更详细的代码:

import UIKit

class PhotoListCollectionViewCell: UICollectionViewCell {

    var mainImageView: UIImageView = {
        let imgV = UIImageView()
        imgV.contentMode = .scaleAspectFill
        return imgV
    }()
    var dateLabel = UILabel()
    var descriptionLabel = UILabel()
    var nameLabel = UILabel()
    var descContainerHeightConstraint = NSLayoutConstraint()
    var photoListCellViewModel : PhotoListCellViewModel? {
        didSet {
            nameLabel.text = photoListCellViewModel?.titleText
            descriptionLabel.text = photoListCellViewModel?.descText
            mainImageView.sd_setImage(with: URL( string: photoListCellViewModel?.imageUrl ?? "" ), completed: nil)
            dateLabel.text = photoListCellViewModel?.dateText
        }
    }

    func setConstraints() {

        addSubview(mainImageView)
        mainImageView.translatesAutoresizingMaskIntoConstraints = false
        mainImageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        mainImageView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
        mainImageView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
        mainImageView.heightAnchor.constraint(equalToConstant: 150)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = .red
        self.setConstraints()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
class CollectionViewController: BaseListController, UICollectionViewDelegateFlowLayout {

    fileprivate let cellId = "cellId"

    lazy var viewModel: PhotoListViewModel = {
        return PhotoListViewModel()
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        initView()
        initVM()
    }

    func initView() {
        self.navigationItem.title = "NavBar"
        collectionView.register(PhotoListCollectionViewCell.self, forCellWithReuseIdentifier: cellId)
        collectionView.backgroundColor = .white
    }

    func initVM() { ... }

    func showAlert( _ message: String ) { ... }

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

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as? PhotoListCollectionViewCell else {
            fatalError("Cell could not be dequeued")
        }
        let cellVM = viewModel.getCellViewModel( at: indexPath )
        cell.photoListCellViewModel = cellVM

        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return .init(width: view.frame.width, height: 150)
    }
}

以下代码最有可能与该问题无关(但出于完整性原因……)

class BaseListController: UICollectionViewController {

    init() {
        super.init(collectionViewLayout: UICollectionViewFlowLayout())
    }

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

我还尝试将imgV.contentMode = .scaleAspectFill更改为imgV.contentMode = .scaleAspectFit。但是然后我松开了图像的整个宽度,如此处的插图所示:

enter image description here

但是我想我越来越近了。理想的设置是什么?

1 个答案:

答案 0 :(得分:1)

我终于找到了解决方法。

Mykod的出色帮助下,我得以解决了在集合视图单元内显示的imageView的contentMode及其锚点约束的问题。

这是解决方案:

PhotoListCollectionViewCell内,您可以设置contentModeclipsToBounce

var mainImageView: UIImageView = {
    let imgV = UIImageView()
    imgV.contentMode = .scaleAspectFill
    imgV.clipsToBounds = true
    return imgV
}()

非常重要的是,您需要将顶部,顶部,尾部和底部约束设置为等于单元格的顶部,顶部,尾部和底部约束:


func setConstraints() {
    addSubview(mainImageView)
    mainImageView.translatesAutoresizingMaskIntoConstraints = false
    mainImageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
    mainImageView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
    mainImageView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
    mainImageView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
}

进行了上述更改后,imageView现在将填满整个屏幕,并被裁剪为正确的高度-即,现在都正确了:)

enter image description here