#swift #uicollectionview
#быстрый #uicollectionview
Вопрос:
Я хочу сделать UICollectionView
с ячейками ширину экрана, но высота зависит от соотношения сторон UIImageView
внутри.
В моей текущей реализации все UICollectionViewCell
экземпляры являются квадратами, и это не то, что я хочу.
Я хочу каким-то образом использовать автоматическую компоновку, чтобы размер изображения соответствовал ширине экрана, но соответствующая высота зависит от соотношения сторон используемого изображения.
Все выполняется программно в коде.
Мой код:
class ViewController: UIViewController {
var data = ["1","2","3","4","5","6","7","8","1","2","3","4","5","6","7","8"]
var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView.dataSource = self
self.collectionView.delegate = self
self.collectionView.register(SubclassedCollectionViewCell.self, forCellWithReuseIdentifier: "cell")
self.collectionView.alwaysBounceVertical = true
self.collectionView.backgroundColor = .white
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
override func loadView() {
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: UIScreen.main.bounds.size.width - 20, height: UIScreen.main.bounds.size.width / 1)
layout.scrollDirection = .vertical
collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
self.view = collectionView
}
}
extension ViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
data.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? SubclassedCollectionViewCell {
let data = self.data[indexPath.item]
cell.setupCell(image: data)
return cell
}
fatalError("Could not dequeue cell")
}
}
с помощью ячейки
class SubclassedCollectionViewCell: UICollectionViewCell {
var hotelImageView: UIImageView = {
var hotelView = UIImageView()
hotelView.contentMode = .scaleAspectFill
hotelView.clipsToBounds = true
return hotelView
}()
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(hotelImageView)
hotelImageView.translatesAutoresizingMaskIntoConstraints = false
hotelImageView.topAnchor.constraint(equalTo: topAnchor).isActive = true
hotelImageView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
hotelImageView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
hotelImageView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupCell(image: String) {
if let image : UIImage = UIImage(named: image) {
hotelImageView.image = image
}
}
}
Ответ №1:
Сначала вычислите соотношение на основе ширины и умножьте на ширину вида коллекции, чтобы получить новую высоту, основанную на ширине.
Окончательный код: удалите itemSize из функции loadview. И вычислите высоту и верните размер элемента в методе sizeForItemAt.
Просмотр загрузки
override func loadView() {
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
// layout.itemSize = CGSize(width: UIScreen.main.bounds.size.width - 20, height: UIScreen.main.bounds.size.width / 1) <-- Remove this
layout.scrollDirection = .vertical
collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
self.view = collectionView
}
UICollectionViewDelegateFlowLayout
extension ViewController: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
data.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? SubclassedCollectionViewCell {
let data = self.data[indexPath.item]
cell.setupCell(image: data)
return cell
}
fatalError("Could not dequeue cell")
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
guard let iamgeData = UIImage(named: self.data[indexPath.item]) else {
return .zero
}
let width = collectionView.bounds.width
let heightOnWidthRatio = iamgeData.size.height / iamgeData.size.width
let height = width * heightOnWidthRatio
return CGSize(width: width, height: height)
}
}