使用swift-5.0.1,iOS-12.2和
我在UICollectionView上观察到一个奇怪的行为:
有些屏幕范围的单元格在我的collectionView中显示图像。
我的观察是,每当无法获取图像时,上述单元格的大小就会比预期的大。问题是为什么??
下图说明了该问题:
任何无法获取的图像显然无法显示,并且其单元格的backgroundColer等于红色。所有这一切。但是,为什么在nil-cell上方的一个单元格的大小增加了??
所有单元格的大小应由黄色框指示。
我在代码中有两个地方可以触摸单元格的高度:
mainImageView.heightAnchor.constraint(equalToConstant: 150)
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
。但是然后我松开了图像的整个宽度,如此处的插图所示:
但是我想我越来越近了。理想的设置是什么?
答案 0 :(得分:1)
我终于找到了解决方法。
在Mykod的出色帮助下,我得以解决了在集合视图单元内显示的imageView的contentMode
及其锚点约束的问题。
这是解决方案:
在PhotoListCollectionViewCell
内,您可以设置contentMode
和clipsToBounce
:
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现在将填满整个屏幕,并被裁剪为正确的高度-即,现在都正确了:)