Reputation: 469
I want to mix the layout flow of a UICollectionView to both vertical and horizontal, i want to have every row divisible by 2 to have a single item, else it should have a two column grid, i have exhausted every approach i can think of, i end of getting one item per row.
The image below is exactly what i want to achieve.
This is what i tried
class TrendVC: UIViewController {
fileprivate let itemsPerRow: CGFloat = 2
fileprivate let sectionInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
@IBOutlet weak var collectionView: UICollectionView!
var data = [ "others", "sports", "kitchen", "phones", "entertainment", "electronics", "women"]
var dataNames = ["Bags", "Sports & Outdoor", "Kitchen Essentials", "Mobile Phones & Tablets", "Entertainment", "Audio and Video", "Women's Clothings"]
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
navigationController?.navigationBar.isTranslucent = true
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
navigationController?.navigationBar.shadowImage = UIImage()
collectionView.dataSource = self
collectionView.delegate = self
collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
extension TrendVC: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item % 3 == 0{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DoubleCell", for: indexPath) as! DoubleTrendCellCell
let datum = data[indexPath.item]
let dat = dataNames[indexPath.item]
cell.trendNameLabel.text = dat
cell.trendImageView.image = UIImage(named: datum)
return cell
}else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TrendCell", for: indexPath) as! SingleTrendCell
let datum = data[indexPath.item]
let dat = dataNames[indexPath.item]
cell.trendNameLabel.text = dat
cell.trendImageView.image = UIImage(named: datum)
return cell
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.item % 3 == 0{
let paddingSpace = sectionInsets.left * (2 + 1)
let availableWidth = view.frame.width - paddingSpace
let widthPerItem = availableWidth / itemsPerRow
return CGSize(width: widthPerItem, height: widthPerItem)
}
let paddingSpace = sectionInsets.left * (2 + 1)
let availableWidth = view.frame.width - paddingSpace
let widthPerItem = availableWidth / itemsPerRow
return CGSize(width: view.frame.width, height: widthPerItem)
}
//3
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
insetForSectionAt section: Int) -> UIEdgeInsets {
return sectionInsets
}
// 4
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return sectionInsets.left
}
}
This is what i am getting
Upvotes: 3
Views: 3662
Reputation: 4222
Since both your cells have the same structure, there is not point in creating two different kinds of cells. All you have to do is use the sizeForItemAtIndexPath
method and return appropriate sizes, autoLayout
will take care of the content inside. Something like:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.item % 3 == 0{
return CGSize(width: collectionView.bounds.size.width/2.0, height: collectionView.bounds.size.height/3.0)
}else{
return CGSize(width: collectionView.bounds.size.width, height: collectionView.bounds.size.height/3.0)
}
}
Note: Ensure all your insets and inter item spacings are 0.
Upvotes: 2
Reputation: 72410
You need to calculate modulo with 3
instead of 2
to get the desired output.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item % 3 == 0{
//return SingleTrendCell
}else{
//return DoubleTrendCellCell
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.item % 3 == 0{
//return SingleTrendCell Size
}
//return DoubleTrendCellCell Size
}
Upvotes: 1