UICollectionView Layout Wrong Item Size - ios

I am programmatically creating a UICollectionViewController:
class MyCollectionVC: UICollectionViewController, UICollectionViewDelegateFlowLayout {
init() {
super.init(collectionViewLayout: UICollectionViewFlowLayout())
}
override func loadView() {
super.loadView()
self.collectionView.delegate = self
...
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout:
UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let dimension = self.view.bounds/3
return CGSize(width: dimension, height: dimension)
}
override final func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
print ("Cell Size: (self.collectionViewLayout as! UICollectionViewFlowLayout).itemSize)
}
}
I need thee actually cell size at cellForItemAt to do more work.
Cell size above prints out 50 x 50 at all times. This is the default size given. iPhone or iPad, portrait of landscape, it is always 50.
The odd thing is, the actual cell layout gets displayed correctly. Everything else works and looks perfectly.
What am I missing here?

Try This
class GridLayout: UICollectionViewFlowLayout {
override init() {
super.init()
self.minimumLineSpacing = 0
self.minimumInteritemSpacing = 0
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func prepare() {
super.prepare()
guard let collectionView = self.collectionView else {return}
let cellWidth = collectionView.frame.width / 3
self.itemSize = CGSize(width: cellWidth, height: cellWidth) // Your Cell Size
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView.collectionViewLayout = GridLayout()
collectionView.delegate = self
collectionView.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
print((self.collectionView.collectionViewLayout as! UICollectionViewFlowLayout).itemSize)
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Your Cell Id", for: indexPath)
return cell
}

Related

UICollectionView inside of UICollectionView with dynamic height

I am trying to create a similar layout to the App store. I have got one collection view that is vertical and inside of it each row is another collection view that is horizontal.
I am trying to use dynamic height so the cell can increase its height based on the content inside. However that never works, it only works when i use sizeForItemAt function to explicitly set it. I would like to also be able to control the width
I have looked at many previous questions such as: UICollectionView, full width cells, allow autolayout dynamic height? however no answer worked for me.
I am really confused on what i am doing wrong.
import UIKit
class HomeViewController: UICollectionViewController {
public override func viewDidLoad() {
super.viewDidLoad()
let collectionViewLayout = UICollectionViewFlowLayout()
collectionViewLayout.scrollDirection = .vertical
collectionViewLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
collectionView.collectionViewLayout = collectionViewLayout
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView?.register(HorizontalCollectionView.self, forCellWithReuseIdentifier: HorizontalCollectionView.reuseIdentifier)
}
public override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
public override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 4
}
public override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: HorizontalCollectionView.reuseIdentifier, for: indexPath) as? HorizontalCollectionView {
return cell
}
return UICollectionViewCell()
}
}
HorizontalCollectionView.swift
import UIKit
class HorizontalCollectionView: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
static let reuseIdentifier = "HorizontalCollectionView"
var cellSpancolumns: CGFloat?
override init(frame: CGRect) {
super.init(frame: frame)
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
collectionView.delegate = self
collectionView.dataSource = self
addSubview(collectionView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented - Storyboards are not used.")
}
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
let collectionView = UICollectionView(frame: bounds, collectionViewLayout: layout)
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.showsHorizontalScrollIndicator = false
return collectionView
}()
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
if (indexPath as NSIndexPath).section == 0 {
cell.backgroundColor = UIColor.blue
} else {
cell.backgroundColor = UIColor.red
}
return cell
}
}

How to add a collectionView inside a uiTableViewCell

I'm trying to add a uicollectionView with 5 cells inside a uitableView cell. I'm running into issues where the collection view is not displaying at all. Here's my code:
// TableViewController
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "book", for: indexPath) as! BookTableViewCell
cell.cellIndex = indexPath
cell.dataSource = self
cell.delegate = self
cell.backgroundColor = UIColor.white
// if let books = all_books[indexPath.section], books.count > 0 {
// cell.collectionView.reloadData()
// }
return cell
}
// BookTableViewCell
import UIKit
import Firebase
import FirebaseDatabase
import SDWebImage
class BookTableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource {
var delegate: BookTableViewCellDelegate?
var dataSource: BookTableViewCellDelegate?
let leftAndRightPaddings: CGFloat = 10.0
let numberOfItemsPerRow: CGFloat = 5
let screenSize: CGRect = UIScreen.main.bounds
var collectionView: UICollectionView!
var tableRowData: Book!
var books : [Book]?
var ref: DatabaseReference!
var cache:NSCache<AnyObject, AnyObject>!
var cellIndex: IndexPath!
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
let flowLayout = UICollectionViewFlowLayout()
flowLayout.scrollDirection = .horizontal
flowLayout.itemSize = CGSize(width: 100, height: self.frame.height)
//You can also provide estimated Height and Width
flowLayout.estimatedItemSize = CGSize(width: 100, height: self.frame.height)
//For Setting the Spacing between cells
flowLayout.minimumInteritemSpacing = 25
flowLayout.minimumLineSpacing = 20
collectionView = UICollectionView(frame: self.bounds, collectionViewLayout: flowLayout)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "collectionCell")
collectionView.showsHorizontalScrollIndicator = false
collectionView.backgroundColor = UIColor.clear
self.addSubview(collectionView)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath as IndexPath) as! BookCollectionViewCell
self.dataSource?.getData(cell: self)
let books = self.books
let book = books?[indexPath.row]
if book != nil {
cell.imageView.sd_setImage(with: URL(string: book?.image as! String), placeholderImage: nil)
cell.label.text = book?.title
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
return CGSize(width: 100, height: self.frame.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets
{
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.dataSource?.getData(cell: self)
let books = self.books
let book = books?[indexPath.row]
if let book = book {
self.delegate?.didSelectCollection(book: book)
}
}
}
protocol BookTableViewCellDelegate {
func getData(cell: BookTableViewCell)
func didSelectCollection(book: Book)
}
Can someone please help? I am initializing the collection view in the init function. Setting up all the delegates correctly. Not sure what I'm doing wrong.
Problem is
collectionView = UICollectionView(frame: self.bounds, collectionViewLayout: flowLayout)
you need to set the frame at correct time not inside init here
override func layoutSubviews() {
super.layoutSubviews()
collectionView.frame = self.bounds
}
or better to use constraints inside init , also add it to
self.contentView.addSubview(collectionview)

Swift using estimatedItemSize for cell breaks cell width during scrolling

ios version 11/12
Trying to make dynamic cell height for UIViewController (cell contains image with fixed height and label that can be multiline because of that label view-cell should be able dynamically change height). I'm using Storyboard to construct basic UI with some constrains that makes cell min width 300.
Getting strange UI behaviour during vertical scrolling in UIViewController. Some cells(that are not in the UI initially) resized to the size defined in Storyboard constrains and ignoring estimatedItemSize
import UIKit
class StartController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
let offers = SearchCategoryOffer.mockOffers
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.view.backgroundColor = UIColor.white
let titleImageView = NavigationImageView()
titleImageView.image = UIImage(named: "logo")
navigationItem.titleView = titleImageView
let w = self.collectionView.frame.width - 30
collectionView.delegate = self
collectionView.dataSource = self
collectionView.translatesAutoresizingMaskIntoConstraints = false
if let layout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.sectionInsetReference = .fromLayoutMargins
layout.sectionInset = UIEdgeInsetsMake(20, 5, 20, 5)
layout.minimumLineSpacing = 26
layout.minimumInteritemSpacing = 0
layout.estimatedItemSize = CGSize(width: w, height: 300) // cell size
}
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return offers.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell: OfferCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! OfferCell
cell.listTitle?.text = offers[indexPath.row].name
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let _: OfferCell = collectionView.cellForItem(at: indexPath) as! OfferCell
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
let _: OfferCell = collectionView.cellForItem(at: indexPath) as! OfferCell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// bla-bla-bla
}
}
class NavigationImageView: UIImageView {
override func sizeThatFits(_ size: CGSize) -> CGSize {
return CGSize(width: 133, height: 35)
}
}

How to expand multiple UICollectionViewCells on tap

I'm trying to build a collectionView that can expand multiple cells after they've been selected/tapped or collapsed when they are deselected, everything works fine when the cells remain on the screen, but once the expanded cells go off screen, I get unexpected behaviour.
For example if I select a cell with IndexPath 0 and then scroll down, tap on cell with IndexPath of 8, scroll back to cell with IndexPath 0 (it's already collapsed), I would tap on it and scroll back to the cell with IndexPath 8 and tap on it again it expands + cell with IndexPath 10 would expand too.
The CollectionView has been implemented programmatically as well the UICollectionViewCell has been subclassed.
ViewController that holds the UICollectionView:
import UIKit
class CollectionViewController: UIViewController {
// MARK: - Properties
fileprivate var collectionView: UICollectionView!
var manipulateIndex: NSIndexPath? {
didSet {
collectionView.reloadItems(at: collectionView.indexPathsForSelectedItems!)
}
}
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
collectionView.dataSource = self
collectionView.delegate = self
collectionView.register(CustomCell.self, forCellWithReuseIdentifier: "Cell")
collectionView.backgroundColor = UIColor.white
self.view.addSubview(collectionView)
}
}
// MARK: - UICollectionViewDataSource
extension CollectionViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 13
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CustomCell
cell.textLabel.text = "\(indexPath.item)"
cell.backgroundColor = UIColor.orange
return cell
}
}
// MARK: - UICollectionViewDelegate
extension CollectionViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
let cell = collectionView.cellForItem(at: indexPath) as! CustomCell
cell.expanded = !cell.expanded
manipulateIndex = indexPath as NSIndexPath
return false
}
}
// MARK: - UICollectionViewDelegateFlowLayout
extension CollectionViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if let cell = collectionView.cellForItem(at: indexPath) as? CustomCell {
if cell.expanded == true {
return CGSize(width: self.view.bounds.width - 20, height: 300)
}
if cell.expanded == false {
return CGSize(width: self.view.bounds.width - 20, height: 120.0)
}
}
return CGSize(width: self.view.bounds.width - 20, height: 120.0)
}
}
And the subclassed custom UICollectionViewCell:
import UIKit
class CustomCell: UICollectionViewCell {
var expanded: Bool = false
var textLabel: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
textLabel = UILabel(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height/3))
textLabel.font = UIFont.systemFont(ofSize: UIFont.smallSystemFontSize)
textLabel.textAlignment = .center
contentView.addSubview(textLabel)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Please help and thank you so much to the amazing person, who can help me out! :)
Try this:
Example 1: Expand only one cell at a time
Note: No need to take expanded bool variable in custom cell
var section:Int?
var preSection:Int?
var expand:Bool = false
extension ViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 13
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CustomCell
cell.textLabel.text = "\(indexPath.item)"
cell.backgroundColor = UIColor.orange
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if (self.section != nil) {
self.preSection = self.section
}
self.section = indexPath.row
if self.preSection == self.section {
self.preSection = nil
self.section = nil
}else if (self.preSection != nil) {
self.expand = false
}
self.expand = !self.expand
self.collectionView.reloadItems(at: collectionView.indexPathsForSelectedItems!)
}
}
// MARK: - UICollectionViewDelegateFlowLayout
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if self.expand, let row = self.section, row == indexPath.row {
return CGSize(width: self.view.bounds.width - 20, height: 300)
}else{
return CGSize(width: self.view.bounds.width - 20, height: 120.0)
}
}
}
Example 2:
Expand multiple cell
import UIKit
class ViewController: UIViewController {
// MARK: - Properties
fileprivate var collectionView: UICollectionView!
var expandSection = [Bool]()
var items = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.items = ["A","B","C","D","E","F","G","H","J","K"]
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
collectionView.dataSource = self
collectionView.delegate = self
collectionView.register(CustomCell.self, forCellWithReuseIdentifier: "Cell")
collectionView.backgroundColor = UIColor.white
self.expandSection = [Bool](repeating: false, count: self.items.count)
self.view.addSubview(collectionView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.items.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CustomCell
cell.textLabel.text = self.items[indexPath.row]
cell.backgroundColor = UIColor.orange
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.expandSection[indexPath.row] = !self.expandSection[indexPath.row]
self.collectionView.reloadItems(at: collectionView.indexPathsForSelectedItems!)
}
}
// MARK: - UICollectionViewDelegateFlowLayout
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if self.expandSection[indexPath.row] {
return CGSize(width: self.view.bounds.width - 20, height: 300)
}else{
return CGSize(width: self.view.bounds.width - 20, height: 120.0)
}
}
}
UICollectionView will reuse your cells for multiple objects in your data model. You can't control which cells get reused when during reloadItems You should not assume that the expanded state in a given cell corresponds to the state of your data model. Instead, you should be holding onto the expanded state somehow in your data model and re-setting that in every call to cellForItemAt.
In other words, hold your state in your model and set the cell state in cellForItemAt, don't hold it in the cells themselves.

UICollectionView in a UICollectionViewCell

I am interested in having a collectionview as a part of a collection view cell but for some reason cannot figure out how this would be done. Where would I implement the necessary methods for the cells collectionview?
There's an article that Ash Furrow wrote that explains how to put an UICollectionView inside an UITableViewCell. It's basically the same idea when using it inside an UICollectionViewCell.
Everything is done programatically. No storyboards.
I added a UICollectionView inside my UICollectionViewCell. I also show how to add again a UICollectionViewCell inside the created UICollectionView to have this result
import UIKit
class CategoryCell: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
private let cellId = "cell"
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let appsCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
return collectionView
}()
func setupViews() {
backgroundColor = .blue
addSubview(appsCollectionView)
appsCollectionView.delegate = self
appsCollectionView.dataSource = self
appsCollectionView.register(AppCell.self, forCellWithReuseIdentifier: cellId)
addConstrainstWithFormat("H:|-8-[v0]-8-|", views: appsCollectionView)
addConstrainstWithFormat("V:|[v0]|", views: appsCollectionView)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
return cell
}
}
class AppCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews(){
backgroundColor = .red
}
}
My UICollectionViewController
import UIKit
class FeaturedAppsController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
let cellId = "cell"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
collectionView?.backgroundColor = .white
collectionView?.register(CategoryCell.self, forCellWithReuseIdentifier: cellId)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(view.frame.width, 150)
}
}
The whole explanation can be found and was developed by "Let´s build that app": https://www.youtube.com/watch?v=Ko9oNhlTwH0&list=PL0dzCUj1L5JEXct3-OV6itP7Kz3tRDmma
This is too late for this answer but it might help others. This is an example of UICollectionView inside a UICollectionViewCell.
Lets start by having a mainCollectionView. Then on each cell of this collection create and initialize a new UICollectionView and right place to do that is in this following delegate of UICollectionView
func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath)
e.g I initialize the MainCollectionViewCell here and then MainCollectionViewCell handles the logic to create a new UICollectionView
guard let collectionViewCell = cell as? MainCollectionViewCell else { return }
collectionViewCell.delegate = self
let dataProvider = ChildCollectionViewDataSource()
dataProvider.data = data[indexPath.row] as NSArray
let delegate = ChildCollectionViewDelegate()
collectionViewCell.initializeCollectionViewWithDataSource(dataProvider, delegate: delegate, forRow: indexPath.row)
collectionViewCell.collectionViewOffset = storedOffsets[indexPath.row] ?? 0
Here is the initializer on MainCollectionViewCell that creates a new UICollectionView
func initializeCollectionViewWithDataSource<D: protocol<UICollectionViewDataSource>,E: protocol<UICollectionViewDelegate>>(dataSource: D, delegate :E, forRow row: Int) {
self.collectionViewDataSource = dataSource
self.collectionViewDelegate = delegate
let flowLayout = UICollectionViewFlowLayout()
flowLayout.scrollDirection = .Horizontal
let collectionView = UICollectionView(frame: self.bounds, collectionViewLayout: flowLayout)
collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseChildCollectionViewCellIdentifier)
collectionView.backgroundColor = UIColor.whiteColor()
collectionView.dataSource = self.collectionViewDataSource
collectionView.delegate = self.collectionViewDelegate
collectionView.tag = row
self.addSubview(collectionView)
self.collectionView = collectionView
collectionView.reloadData()
}
Hope that helps !!
I did an example for this and put in on github. It demonstrates the use UICollectionView inside a UICollectionViewCell.
https://github.com/irfanlone/Collection-View-in-a-collection-view-cell
Easiest solution for collectionview inside collectionview using storyboard and Swift 5
Please refer this link for nested collectionview example
import UIKit
class ParentViewController:UIViewController,UICollectionViewDataSource,UICollectionViewDelegate {
//MARK: Declare variable
//MARK: Decalare outlet
#IBOutlet weak var outerCollectionView: UICollectionView!
#IBOutlet weak var pageControl: UIPageControl!
let outerCount = 4
//MARK: Decalare life cycle methods
override func viewDidLoad() {
super.viewDidLoad()
pageControl.numberOfPages = outerCount
}
//MARK: Collection View delegate methods
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return outerCount
}
//MARK: Collection View datasource methods
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "OuterCell", for: indexPath) as! OuterCollectionViewCell
cell.contentView.backgroundColor = .none
return cell
}
//MARK:- For Display the page number in page controll of collection view Cell
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let visibleRect = CGRect(origin: self.outerCollectionView.contentOffset, size: self.outerCollectionView.bounds.size)
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
if let visibleIndexPath = self.outerCollectionView.indexPathForItem(at: visiblePoint) {
self.pageControl.currentPage = visibleIndexPath.row
}
}
}
class OuterCollectionViewCell: UICollectionViewCell ,UICollectionViewDataSource,UICollectionViewDelegate {
#IBOutlet weak var InnerCollectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
InnerCollectionView.delegate = self
InnerCollectionView.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
6
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "InnerCell", for: indexPath) as! InnerCollectionViewCell
cell.contentView.backgroundColor = .green
return cell
}
}
class InnerCollectionViewCell: UICollectionViewCell{
}

Resources