Custom Layout UICollectionView - ios

How do I set a horizontal orientation to a collection view in Swift? I need want the row layout to be like the picture below.

#IBOutlet weak var collectionView: UICollectionView!
let cellIdentifier = "cellViewID"
let objects = ["Cat", "Dog", "Fish"]
let images_array = ["break_down_grey", "break_down_grey", "Fish"]
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return objects.count;
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! CustomCollectionViewCell
cell.title.text=objects[indexPath.row]
cell.imageView.image = UIImage(named: images_array[indexPath.row])
print(cell)
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Cell \(indexPath.row) selected")
}
import UIKit
class CustomCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var title: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}

Related

Collectionview rows showing wrongly with JSON data in swift

I am using collectionview in tableview cell
class CategoryNewVC: UIViewController {
#IBOutlet weak var categoryTableview: UITableView!
public var activeCategories : Array<Category_json>?
override func viewDidLoad() {
super.viewDidLoad()
self.activeCategories = homeData?.result?.category_json?.filter({ (item) -> Bool in
return item.status == "A"
})
categoryTableview.reloadData()
}
this is the code for tableview and collectionview
extension CategoryNewVC : UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.activeCategories?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryNewTableCell", for: indexPath) as! CategoryNewTableCell
let indexData = self.activeCategories?[indexPath.row]
cell.catNameLbl.text = indexData?.details?.first?.title
cell.activeCategories = self.activeCategories
cell.clcSeller.reloadData()
return cell
}
}
class CategoryNewTableCell: UITableViewCell,UICollectionViewDelegate,UICollectionViewDataSource{
#IBOutlet weak var catNameLbl: UILabel!
#IBOutlet weak var clcSeller: UICollectionView!
public var activeCategories : Array<Category_json>?
override func awakeFromNib() {
super.awakeFromNib()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.activeCategories?[section].sub_categories?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SubCatCollectionCell", for: indexPath) as! SubCatCollectionCell
let activesubCat = self.activeCategories?[indexPath.section].sub_categories
let indexData = activesubCat?[indexPath.item]
cell.lblTitle.text = langType == .en ? indexData?.details?.first?.title : indexData?.details?[1].title
return cell
}
}
with the above code i am getting number of rows for tableview is correct, but in collectionview numberOfItemsInSection coming wrong.. here in every section it showing only first section values in collectionview.. why?
please do help with the code
In the CategoryNewTableCell, you need to make following changes -
public var subCategories : Array<..>? // Array of your subcategories for a particular tableViewCell
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.subCategories?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SubCatCollectionCell", for: indexPath) as! SubCatCollectionCell
// Change here
let subCategory = self.subCategories?[indexPath.item]
cell.lblTitle.text = langType == .en ? subCategory?.details?.first?.title : subCategory?.details?[1].title
return cell
}
Finally you need to pass subCategories to your tableViewCell like this - from cellForRow implementation -
cell.subCategories = indexData?.sub_categories

Creating a child view controller from a collection view

I am trying to create a child view for my collection view, but whenever I run the app and select a cell from the collection view, nothing appears. How do I fix this so that the tableView is then displayed once a cell is selected?
Here is the code for my collectionView.
import UIKit
class ContentViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
let imageArray = [UIImage(named: "image 1"), UIImage(named: "image 2"), UIImage(named: "image 3")]
override func viewDidLoad() {
super.viewDidLoad()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCell
cell.mapIconImage.image = imageArray[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let child = MapItemsViewController()
addChild(child)
view.addSubview(child.view)
child.didMove(toParent: self)
}
class CustomCell: UICollectionViewCell {
#IBOutlet weak var mapIconImage: UIImageView!
}

IOS Swift Thread Abort Error when Appending image to an image array

I get this error when I try to append an image to my image array in IOS swift: Thread 1:signal SIGABRT
It occurs when I call the loadImages() function:
import UIKit
class ProtectedGallery: UIViewController, UICollectionViewDataSource {
#IBOutlet weak var imageCollection: UICollectionView!
var images = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
loadImages()
}
func loadImages()
{
images.append(UIImage(named: "image1")!)
self.imageCollection.reloadData()
}
func collectionView(_ imageCollection: UICollectionView, numberOfItemsInSection section: Int)-> Int{
return images.count
}
func collectionView(_ imageCollection: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = imageCollection.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! ImageCollectionViewCell
let image = images[indexPath.row]
cell.imageView.image = image;
return cell
}
}
Any ideas why this is the case? I have been stuck on this for a while.
I've just noticed a few things:
First, you never set the data source (or delegate) for your collection view. Do that:
class ProtectedGallery: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var imageCollection: UICollectionView! {
didSet {
imageCollection.dataSource = self
imageCollection.delegate = self
}
}
}
Also, your data source method arguments are not named correctly. Change to this:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// put your code here
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// put your code here
}

Display different arrays in collectionView after click on different rows in tableView

In my viewController i have tableView and collectionView.
And i try to display different arrays in collectionView when i click on different rows in tableView.
So when i click on firstRow in tableView, i want to display firstArray in collectionView, when i click on secondRow in tableView, i want to display secondArray in collectionView and when i click on thirdRow in tableView, i want to display thirdArray in collectionView.
How can i do this?
My test code:
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var tableView: UITableView!
var tableArray: [String] = ["1", "2", "3"]
var secondArray: [String] = ["One", "Two"]
var thirdArray: [String] = ["Three", "Four"]
var fourthArray: [String] = ["Five", "Six"]
// TABLEVIEW
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! TableCell
cell.tableLabel.text = tableArray[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(indexPath)
}
// COLLECTIONVIEW
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return secondArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! CollectionCell
cell.collectionLabel.text = secondArray[indexPath.item]
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(indexPath)
}
}
class TableCell: UITableViewCell {
#IBOutlet weak var tableLabel: UILabel!
}
class CollectionCell: UICollectionViewCell {
#IBOutlet weak var collectionLabel: UILabel!
}
I understand what need to use condition if, but how to use correct it?
You may add your arrays inside a dictionary (collectionData) using the index as key, in this way their lookup is totally dynamic and you don't need any if then else, so your code might be:
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var tableView: UITableView!
var tableArray: [String] = ["1", "2", "3"]
// you may want to feed the dictionary directly with the arrays (feel free to remove them)
var collectionData: [Int: [String]] = [:]
var secondArray: [String] = ["One", "Two"]
var thirdArray: [String] = ["Three", "Four"]
var fourthArray: [String] = ["Five", "Six"]
override func viewDidLoad() {
super.viewDidLoad()
self.collectionData[0] = secondArray
self.collectionData[1] = thirdArray
self.collectionData[2] = fourthArray
}
func getCurrentArray() -> [String]? {
let currentRow = self.tableView.indexPathForSelectedRow?.row ?? 0
let array = self.collectionData[currentRow]
return array
}
// TABLEVIEW
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! TableCell
cell.tableLabel.text = tableArray[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.collectionView.reloadData()
}
// COLLECTIONVIEW
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.getCurrentArray()?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! CollectionCell
cell.collectionLabel.text = self.getCurrentArray()?[indexPath.item]
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(indexPath)
}
}
class TableCell: UITableViewCell {
#IBOutlet weak var tableLabel: UILabel!
}
class CollectionCell: UICollectionViewCell {
#IBOutlet weak var collectionLabel: UILabel!
}
You can create a dictionary and use it. And with the help of key you can easily fetch the different data from different table view cell.

swift : tableViewcell initialization

I have a custom UITableViewCell class which has a collectionview inside. In this class there's a varaible "nbElements" which contain the number of collectionview cells to display. I want to know how I can initialize the value of nbElements when I create a tableview cell with dequeueReusableCell?
Here is the code of the custom tableview cell:
class CustomTableViewCell: UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var collectionViewHeightConstraint: NSLayoutConstraint!
var nbElements = Int!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.collectionView.register(UINib(nibName: "CustomCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "customCollectionViewCell")
self.collectionViewHeightConstraint.constant = self.collectionView.collectionViewLayout.collectionViewContentSize.height
}
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 nbElements
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "customCollectionViewCell", for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let cellWidth = (self.collectionView.frame.width / 2.0) - 1
let size = CGSize.init(width: cellWidth, height: cellWidth)
return size;
}
}
Here is the code when I create a tableview cell:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customTableViewCell", for: indexPath) as! CustomTableViewCell
cell.nbElements = 4
return cell
}
Regards.
Trigger reload of collectionView whenever the nbElements is set.
var nbElements = Int! {
didSet {
collectionView.reloadData()
}
}

Resources