I am using LBTAComponents pod
this is a pod that makes easier to work with UICollectionView
without any need to register anything and provides a super simple anchoring system ... and in the first project I've got two days ago I decided to use this framework
but now I have a problem in one of uicollectionviewCells I need another collectionview that I can fill with items then I need it to be scrollable horizontally
import LBTAComponents
import UIKit
class ProductCell: DatasourceCell {
let cellId = "cellid"
let collectionView : UICollectionView = {
let layout = UICollectionViewFlowLayout()
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.backgroundColor = .black
return cv
}()
override func setupViews() {
super.setupViews()
ProductCell.addSubview(collectionView)
collectionView.frame = frame
collectionView.register(UICollectionView.self, forCellWithReuseIdentifier: cellId)
collectionView.dataSource = self
}
}
extension ProductCell : UICollectionViewDataSource{
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)
cell.backgroundColor = .white
return cell
}
}
datasourceCell is equal to UICollectionViewCell in this pod.
and now I am getting this ERROR :
instance member 'addsubview' cannot be used on type uiview did you use the value of this type instead?
could you please help me?
I tried to use self.addSubview(collectionView)
but I got another error enter image description here
You can simply use a UITableView with custom UITableViewCells containing a UICollectionView.
Example:
1. View Hierarchy
2. UIViewController containing UITableView
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
return tableView.dequeueReusableCell(withIdentifier: "tcell", for: indexPath) as! TableCell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
if indexPath.row == 0
{
return 120
}
else
{
return 150
}
}
}
3. Custom UITableViewCell containing UICollectionView
class TableCell: UITableViewCell, UICollectionViewDataSource
{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 3
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
return collectionView.dequeueReusableCell(withReuseIdentifier: "ccell", for: indexPath)
}
}
4. Output Screenshot
addsubview is an instance method, not a class method. So you should use:
self.addSubview(collectionView)
instead of:
ProductCell.addSubview(collectionView)
Related
I have implemented this:
By following this tutorial.
Here's the problem:
I am unable to scroll through the collection items.
I think this has something to do with the fact that the project I followed is for iOS and my project is for tvOS.
I've found a somewhat similar question. An answer linked to this GitHub Repo whose implementation doesn't seem that different from mine.
Here's the relevant code:
ViewController.swift
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell =
tableView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath) as? TableViewCell
else {
fatalError("Unable to create explore table view cell")}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 140
}
}
tableViewCell.swift
class TableViewCell: UITableViewCell {
#IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
collectionView.delegate = self
collectionView.dataSource = self
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
extension TableViewCell: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 50
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// For some reason he chose the measures of collectionViewCell and substracted 2
return CGSize(width: 139, height: 64)
}
// Highlight the current cell
// This doesn't work
func collectionView(_ collectionView: UICollectionView, didUpdateFocusIn context: UICollectionViewFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
if let pindex = context.previouslyFocusedIndexPath, let cell = collectionView.cellForItem(at: pindex) {
cell.contentView.layer.borderWidth = 0.0
cell.contentView.layer.shadowRadius = 0.0
cell.contentView.layer.shadowOpacity = 0.0
}
if let index = context.nextFocusedIndexPath, let cell = collectionView.cellForItem(at: index) {
cell.contentView.layer.borderWidth = 8.0
cell.contentView.layer.borderColor = UIColor.orange.cgColor
cell.contentView.layer.shadowColor = UIColor.orange.cgColor
cell.contentView.layer.shadowRadius = 10.0
cell.contentView.layer.shadowOpacity = 0.9
cell.contentView.layer.shadowOffset = CGSize(width: 0, height: 0)
collectionView.scrollToItem(at: index, at: [.centeredHorizontally, .centeredVertically], animated: true)
}
}
}
In a separate project, I have implemented a collectionView independently. I.e: It was not embedded inside of a tableView. And it works just fine.
I copied the code from that project that highlights the selected cell and added it to the tableViewCell.swift but it had no impact at all.
So my question is:
Why am I unable to select a cell and/or scroll through the
collectionView?
Found the answer here:
By denying the focus of the table cell, the Focus engine will
automatically find the next focusable view on the screen. And in your
case, that is the collection view’s cell.
func tableView(_ tableView: UITableView, canFocusRowAt indexPath: IndexPath) -> Bool {
return false
}
Currently, I have a UITableView with a UICollectionView embedded in it. I have 3 arrays of information and I want each array to correspond to a UICollectionView, and therefore a UITableViewCell.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CookieCell", for: indexPath) as? MenuCollectionViewCell
cell?.fullView.layer.borderColor = UIColor.black.cgColor
cell?.labelView.layer.borderColor = UIColor.black.cgColor
cell?.fullView.layer.borderWidth = 0.3
cell?.labelView.layer.borderWidth = 0.3
return cell!
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
}
Where each of the return cell? is, I want to do something like:
if indexPathOfTableView.row == 0 {
//designated parameters
}
else if indexPathOfTableView.row == 1 {
//designated parameters
}
else {
//designated parameters
}
How would I do this?
Hello #helloworld12345
from your question I got the idea that you want to collectionview in tableviewcell
may be below code will help you.
first in you viewController or tableviewcontroller,
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
//send indexPath of this cell
let cell = tblView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath) as! tableViewCell
//Pass your array which you want to show in collectionViewCell and then reload collection view
cell.clnView.reloadData()
return cell
}
In your tableViewCell swift file:
class tableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
{
#IBOutlet weak var clnView: UICollectionView!
//after awakenib method write below code
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 4 //pass your array count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
let flowayout = collectionViewLayout as? UICollectionViewFlowLayout
let space: CGFloat = (flowayout?.minimumInteritemSpacing ?? 0.0) + (flowayout?.sectionInset.left ?? 0.0) + (flowayout?.sectionInset.right ?? 0.0)
let size:CGFloat = (self.clnView.frame.size.width - space) / 2.0 //By this you can show two cell in one screen
return CGSize(width: size + 60, height: (size + 200))
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "clnViewCell", for: indexPath) as! clnViewCell
// do your stuff with your
return cell
}
}
Have an issue where:
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
is called when an item is selected, but I cannot change any cell properties from this method.
I created a new project with a stripped down UICollectionViewController to change the background color of a cell when selected. It also doesn't work. Here it is:
import UIKit
private let reuseIdentifier = "Cell"
class CollectionViewController: UICollectionViewController {
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
cell.backgroundColor = UIColor.blue
return cell
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = self.collectionView(self.collectionView, cellForItemAt: indexPath)
cell.backgroundColor = UIColor.green
}
}
The only thing I did in Storyboard is delete the standard View Controller and replace it with a UICollectionViewController, create a subclass of UICollectionViewController and set the controller in the storyboard as that class.
Also, I can confirm that the cell's index path is returned from this method when called from inside the didSelectItemAt method:
self.collectionView.indexPathsForSelectedItems
You are using the wrong API. Never call the delegate method collectionView(_ cellForItemAt:, use cellForItem(at:
if let cell = collectionView.cellForItem(at: indexPath) {
cell.backgroundColor = UIColor.green
}
But be aware that this change is not persistent. When the user scrolls the color will change back to blue.
You can achieve that as below,
ViewController
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ColoursViewCell", for: indexPath) as! ColoursViewCell
return cell
}
UICollectionViewCell
class ColoursViewCell: UICollectionViewCell {
#IBOutlet var photoImageView: UIImageView?
override var bounds: CGRect {
didSet {
self.layoutIfNeeded()
}
}
override var isSelected: Bool{
didSet{
if self.isSelected{
self.photoImageView?.backgroundColor = UIColor.random
}else{
self.photoImageView?.backgroundColor = UIColor.lightGray
}
}
}
}
you can have sample projects from this link I have in GitHub
https://github.com/hadanischal/RandomColors/tree/develop
I have a collection view which is nested inside of a table view cell. The first cell in the collection view is a button which allows users to create a new list. Its width is smaller than that of the main lists cells. I recently changed the code around so that the collectionView delegate and dataSource methods are in the tableViewController instead of the table view cell, however now the first cells width is not changing as it did before moving the code. This picture shows:
If I press into the blank space it is registering that I clicked the plus cell.
The code for all the collectionView delegate and dataSource methods:
extension ProfileTableViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print("the media: \(usersLists.count)")
return usersLists.count + 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "addNewListCell", for: indexPath) as! addNewListCell
cell.currentUser = currentUser
return cell
}else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as! userListsCell
cell.layer.applySketchShadow()
cell.layer.cornerRadius = 20
cell.layer.masksToBounds = false
cell.currentUser = currentUser
cell.media = usersLists[indexPath.item-1]
return cell
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize{
if indexPath.item == 0 {
let size = CGSize(width: 80, height: 158)
return size
}else{
let size = CGSize(width: 158, height: 158)
return size
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.item == 0 {
//button
self.addListDelegate?.addNewItem()
}
}
I tested if changing any values in the size in sizeForItemAt would change the cell size and nothing changes in any cells
the table view methods which are in the ProfileTableViewController class and not the extension:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "profileCell", for: indexPath) as! profileCell
cell.selectionStyle = .none
return cell
}
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let tableViewCell = cell as? profileCell else { return }
tableViewCell.setCollectionViewDataSourceDelegate(dataSourceDelegate: self, forRow: indexPath.row) //this line sets the collectionView delegate and datasouce so that I can have all of the collectionView methods in this class
}
and this is the code inside of the tableViewCell
protocol addListCollectionDelegate: class {
func addNewItem()
}
class profileCell: UITableViewCell, UICollectionViewDelegate {
#IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
collectionView.register(UINib(nibName: "usersLists", bundle: nil), forCellWithReuseIdentifier: "listCell")
collectionView.register(UINib(nibName: "newListCell", bundle: nil), forCellWithReuseIdentifier: "addNewListCell")
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func setCollectionViewDataSourceDelegate
<D: UICollectionViewDataSource & UICollectionViewDelegate>
(dataSourceDelegate: D, forRow row: Int) {
collectionView.delegate = dataSourceDelegate
collectionView.dataSource = dataSourceDelegate
collectionView.reloadData()
}
}
Does anyone know how to change the width of the first cell since sizeForItemAt is not changing the size? Thanks
You forgot to add this protocol: UICollectionViewDelegateFlowLayout
It is required when you want to return custom size for an item.
Also improve your code like below:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "addNewListCell", for: indexPath) as! addNewListCell
cell.currentUser = currentUser
return cell
}
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as! userListsCell
cell.layer.applySketchShadow() // Write this line in cell class
cell.layer.cornerRadius = 20 // Write this line in cell class
cell.layer.masksToBounds = false // Write this line in cell class
cell.currentUser = currentUser
cell.media = usersLists[indexPath.item - 1]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize{
return indexPath.item == 0 ? CGSize(width: 80, height: 158) : CGSize(width: 158, height: 158)
}
Try to use UICollectionViewDelegateFlowLayout method. In Xcode 11 or later, you need to set Estimate Size to none from Xib.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout:
UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let padding: CGFloat = 170
let collectionViewSize = advertCollectionView.frame.size.width - padding
return CGSize(width: collectionViewSize/2, height: collectionViewSize/2)
}
I am trying to set up UICollectionView in my view controller. I am created custom cell CVCell.xib. My collection view is not showing up at all. What's missing in my code?
In my viewController.swift file:
#IBOutlet var collectionViewNew: UICollectionView?
override func viewDidLoad() {
super.viewDidLoad()
self.collectionViewNew?.registerNib(UINib(nibName: "CVCell", bundle: nil), forCellWithReuseIdentifier: "CVCell")
}
func numberOfSectionsInCollectionView(
collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return 6
}
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CVCell", forIndexPath: indexPath) as CVCell
cell.backgroundColor = UIColor.orangeColor()
return cell
}