I need to create a collectionView A contains few types of cells. One of the cell contains collectionView B that can scroll horizontally. So collectionView A will scroll vertically.
Can I know how to create it and how to display the data into collectionView B?
Thanks again guys
Collection A have Cells lets call our target cell as ASubCell
then at ASubCell we will have Collection B with all of its delegate , and you will create delegate say ASubCellDelegate to send action on Collection B to ViewController of Collection A , here example
import UIKit
protocol ASubCellDelegate {
// CollectionView Cell Pressed
func onSubCellAtcolectionBPressed(_item : YourData)
}
class ASubCell: UICollectionViewCell {
#IBOutlet weak var collectionViewB : UICollectionView!
var delegate : ASubCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
// setup your Collection View B
}
}
// set up your horizontal Collection View
extension UICollectionViewCell:UICollectionViewDelegate,UICollectionViewDataSource {
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourBCellID", for: indexPath) as! YourBCellID
return cell
}
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if delegate != nil {
self.onSubCellAtcolectionBPressed(YourData)
}
}
}
Related
Say, I have a ViewControllerA with a tableView, and that tableView has its header view created and loaded using xib method, and that headerView contains a .horizontal scroll direction collectionView, my question is how would I update the contents of my tableView on click initiated by the collectionView inside the headerView?
similar example is in the below picture:
say, I clicked the "Research" label on the UICollectionViewCell inside the Tableview's HeaderView and the tableView reloads data of "Research", and next I clicked the "Design" label, and the tableView reloads the itself and displays data for "Design".. something like that is possible? i am stuck here.. .
link the header UICollectionView to an outlet in the storyboard, then implement all the required delegate methods.
Add this delegate method:
class ViewController: UIViewController{
var categories = [String]()
var discoverData = [discoverModel]()
var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
categories.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//code to initialize cells of header collecionView
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedCategory = categories[indexPath.row]
let cellToReload = discoverData.filter{return $0.serviceName == selectedCategory}[0]
guard let indexPathsOfCellToRealod = discoverData.firstIndex(of: cellToReload) else { return }
tableView.reloadRows(at: [IndexPath(index: indexPathsOfCellToRealod)], with: .automatic)
}
}
struct discoverModel: Equatable{
var image: UIImage
var serviceName: String
var name: String
var description: String
}
To make this work, just add the standard UITableView delegate methods to your ViewController
I'm looking for your help for my association between a tableview and a collection view.
I've got a CollectionView with 6 horizontal scrollable cells.
In each cell, I would like to put a table view.
For each tableView, I need to know in which cell I am to put my wanted data.
Actually, I make my code work for displaying tableView inside the cells but I'm blocked for finding in which collection view cell I am.
BTW, my Meal_vc_cell controller is actually Empty, it just has a simple outlet. Nothing else.
Here is my code
class TrainFoodPlanViewController: BaseViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UITableViewDataSource, UITableViewDelegate {
let train_meals_list: [String] = ["breakfast", "snack_1", "pre_intra_post", "lunch", "snack_2", "diner"]
#IBOutlet weak var trainCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Food Plan"
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return UITableViewCell()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return train_meals_list.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collection_cell", for: indexPath) as! Meal_vc_cell
cell.meal_number.text = train_meals_list[indexPath.row]
return cell
}
}
Here is what I'm trying to do
There are a number of ways this can be achieved. My recommendation is to subclass UITableView and add a parentCollectionViewIndexPath property
class MyCustomTableView: UITableView {
var parentCollectionViewIndexPath: IndexPath?
}
I'm assuming Meal_vc_cell has an outlet to the relevant tableView. Change that tableView's type to MyCustomTableView
class Meal_vc_cell: UITableViewCell {
#IBOutlet weak var tableView: MyCustomTableView
}
Note: If you're using storyboard, don't forget to update the tableView's class in storyboard as well
Now, just set parentCollectionViewIndexPath in the collectionView's cellForItemAt method
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collection_cell", for: indexPath) as! Meal_vc_cell
cell.tableView.parentCollectionViewIndexPath = indexPath
return cell
}
I have a UICollectionViewCell. This Cell is registered in another UICollectionViewCell, which in turn is registered in viewDidLoad of a UIViewController called FilterCollectionViewController. When the first cell is selected it should pass a value of type String to a UIButton. This UIButton is located in FilterCollectionViewController
In the FilterCollectionViewController I made a variable called colorName
var colorName: String!{
didSet {
print(colorName)
}
}
in the same class there is a UIButton.
#objc func addButtonFunc(sender:UIButton){
print(colorName)
}
In FilterCollectionViewController I declare a UICollectionView. Within this collectionView there is a "second" UICollectionView, which has the function:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let filterVC = FilterCollectionViewController()
filterVC.colorName = "blau"
}
When clicking on a cell from the second UICollectionView I can print the colorName value, from the didSet (in the main FilterCollectionViewController). However, I want it to be passed to the UIButton. When this UIButton is clicked it should process this string further. However the print method results in nil
You should not create a new instance of FilterCollectionViewController if you are in the same class, other things look fine,
Create a variable like,
var colorName: String {
didSet {
print(colorName)
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
colorName = "blau"
}
Then in addButton action,
#objc func addButton(sender: UIButton){
print(colorName)
}
First you have to go to storyboard and set identifier "yourViewId" to
FilterCollectionViewController
then
in this method
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let viewController = self.storyboard.instantiateViewController(withIdentifier:"yourViewId") as! FilterCollectionViewController
viewController.colorName = "red"
self.present(viewController, sender:nil)
}
I found the answer to the problem.
In the parent FilterCollectionViewController I made a variable colorName like
var colorName: String!
in the second UIVieControllerCell I declared a variable of the Parent ViewController Class
var colorName: FilterCollectionViewController?
Thereby in the second UICollectionView at the function didSelectItemsAtI added the following code
colorName?.colorName = "blau"
This had to be declared again in the first UICollectionview, the parent of the second UICollectionView and a child of FilterCollectionViewController. The declaration was in the function cellForItemAt
cell.colorName = self
And that is it. The color name is updated when clicking the button.
Here is the abbreviated Code:
class FilterCollectionViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
var colorName: String!
override func viewDidLoad() {
super.viewDidLoad()
//...register UICollectionview declare button etc.
}
#objc func addButtonFunc(sender:UIButton){
print(colorName)
}
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) as! FilterCell
cell.colorName = self
return cell
}
And in the FilterCell class:
var colorName: FilterCollectionViewController?
//Class is initialised with function, in the function another UUICollectionView is registered.
//...functions like numberOfItemsInSection and cellForItemAt are declared
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
colorName?.colorName = "blau"
}
I am experimenting with UICollectionView and am only using Storyboard - no code at all. I set the number of items to 3 and gave each cell a different color and reuse identifier in the storyboard. Yet the CollectionView (pinkish background) is shown but no cells are shown. What am I missing?
Thanks in advance
-SR
Short Answer
UICollectionView doesn't support static content layouts.
Discussion
But there is a way to simulate it through code. I recommend this great article.
You don't have any code in your ViewController.swift. You can add something like this:
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var menuItems = ["Aap","Koe","Vis","Paard", "Leeuw", "Varken"]
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return menuItems.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
if let c = cell as? AangepasteCollectionViewCell {
c.cellLabel.text = menuItems[indexPath.row].capitalized
}
return cell
}
}
For this example you have to give the collection cell the name cell in the atribute inspector
I have a collection view, and each collection view cell will have a table view which will have different data for each collection view cell. The collection view is done using a storyboard and works fine, but I can not seem to get a UITableView to work inside of it. The Collection view code is below and any help is appreciated. Ideally a technique that allows me to use storyboard to customise the tableview cell, and I am using Swift 4.
extension StoryboardViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt
indexPath: IndexPath) {
print("Selected Cell #\(indexPath.row)")
}
}
extension StoryboardViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 6
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: "CollectionViewCell"), for: indexPath) as! StoryboardCollectionViewCell
cell.label.text = "Cell #\(indexPath.row)"
return cell
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
print("Current centered index: \(String(describing: centeredCollectionViewFlowLayout.currentCenteredPage ?? nil))")
}
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
print("Current centered index: \(String(describing: centeredCollectionViewFlowLayout.currentCenteredPage ?? nil))")
}
}
And I want to put a table view (list) inside of it like so:
UICollectionViewCell class that is being used should conform to UITableViewDelegate and UITableViewDataSource protocols that will initialize the cells in the table view
Your UICollectionViewCell Class should confirm to Protocols, UITableViewDelegate and UITableViewDataSource
import UIKit
class CollectionViewCell: UICollectionViewCell,UITableViewDelegate,UITableViewDataSource {
//MARK: TableViewDelegateAndDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//Configure your cell here
return UITableViewCell()
}
}
Finally don't forget to assign TableView DataSource and Delegate in your storyboard