uicollectionviewcells not showing [duplicate] - swift

I have got this Swift code
`
let cellId="cellId"
class FeedController: UICollectionViewController{
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Centill"
collectionView?.reloadData()
collectionView?.backgroundColor = UIColor(white: 0.95, alpha: 1)
collectionView?.register(FeedCell.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);
cell.backgroundColor = .yellow
return cell
}
}
class FeedCell: 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 = .yellow
}
}
`
But unfortunately my cells are not showing.It only shows navigation bar and background color.what may be the problem with my code?

Try This code:
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
layout.itemSize = CGSize(width: 60, height: 60)
let myCollectionView:UICollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
myCollectionView.dataSource = self
myCollectionView.delegate = self
myCollectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "MyCell")
myCollectionView.backgroundColor = UIColor.whiteColor()
self.view.addSubview(myCollectionView)

You have to provide the size for collection view cell. add the below code snippet
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// calculate and return the height
}

In your cellForItemAt dataSource method you need to give custom UICollectionCell Class
let cell=collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! FeedCell
cell.backgroundColor = .yellow
return cell
Then you will able to see cell.

Try it.
You add in the class
UICollectionViewDataSource and UICollectionVIewDelegate.

Related

Adding a CollectionViewController as a subView

Using Swift 5.1.3, iOS13.3, XCode11.3,
I try to display a horizontal collectionView that is wider than the view's width.
By dragging, the collectionView cells shall scroll horizontally.
The problem now is the following: As soon as I click to drag, the collectionView content "disappears" (i.e. turns transparent). If you look carefully, you can see that the scrollbar is still there.
Why is does the collectionView content turns transparent as soon as I click into it ?
Here is a video illustrating the error behaviour:
Below you will find the corresponding code:
Here is the code:
Inside my Main-ViewController I add the collectionView:
override func viewDidLoad() {
super.viewDidLoad()
let cardsHorizontalController = CardsHorizontalController()
self.view.addSubview(cardsHorizontalController.view)
cardsHorizontalController.view.translatesAutoresizingMaskIntoConstraints = false
cardsHorizontalController.view.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 100.0).isActive = true
cardsHorizontalController.view.heightAnchor.constraint(equalToConstant: 279).isActive = true
cardsHorizontalController.view.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width).isActive = true
}
Here is the collectionView controller class:
class CardsHorizontalController: BaseListController, UICollectionViewDelegateFlowLayout {
let cellId = "cellId"
override func viewDidLoad() {
super.viewDidLoad()
collectionView.backgroundColor = .clear
collectionView.register(CardHeaderCell.self, forCellWithReuseIdentifier: cellId)
if let layout = collectionViewLayout as? UICollectionViewFlowLayout {
layout.scrollDirection = .horizontal
}
collectionView.contentInset = UIEdgeInsets(top: 100, left: 0, bottom: 0, right: 0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return .init(width: view.frame.width - 48, height: view.frame.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return .init(top: 0, left: 16, bottom: 0, right: 0)
}
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
}
}
And its corresponding parent class:
class BaseListController: UICollectionViewController {
init() {
super.init(collectionViewLayout: UICollectionViewFlowLayout())
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
And here the collectionView cell at play:
class CardHeaderCell: UICollectionViewCell {
let imageView = UIImageView(cornerRadius: 8)
override init(frame: CGRect) {
super.init(frame: frame)
imageView.backgroundColor = .red
let stackView = VerticalStackView(arrangedSubviews: [
// companyLabel,
// titleLabel,
imageView
], spacing: 12)
addSubview(stackView)
stackView.fillSuperview(padding: .init(top: 16, left: 0, bottom: 0, right: 0))
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
}
I finally found a solution:
The collectionView-Controller (i.e. CardsHorizontalController()) needs to be added as a ChildController!
Inside Main-ViewController's viewDidLoad()(in first paragraph of code above), please replace the following line...
self.view.addSubview(cardsHorizontalController.view)
with the following:
self.addChild(cardsHorizontalController)
self.view.addSubview(cardsHorizontalController.view)
self.didMove(toParent: cardsHorizontalController)
Having done so, everything works as expected !
You find a working project (stripped-down with only the CollectionView) in this GitHub repo: https://github.com/iKK001/HorizontalCollectionViewExample
And since I'm so happy - here a video of the working horizontal CollectionView:
Have you tried changing return .init(width: view.frame.width - 48, height: view.frame.height) inside sizeForItemAt to return .init(width: collectionView.frame.width - 48, height: collectionView.frame.height)?

How do you add UILabel and UIImageView to a CollectionView programmatically?

I've created a collection view programmatically and can't figure out how to add labels and a background image to the cells. Here's the code I have so far for the collection view.
import UIKit
class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
let cell = "cellId"
let text = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Vote"
collectionView?.backgroundColor = UIColor.white
collectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cell)
}
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: self.cell, for: indexPath)
cell.backgroundColor = UIColor.lightGray
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: 200)
}
}
A simple custom UICollectionViewCell class would look like this:
class MyCell : UICollectionViewCell {
var label1: UILabel
var label2: UILabel
var bgImg: UIImageView
}
Edit the viewDidLoad function:
collectionView?.register(MyCell.self, forCellWithReuseIdentifier: cell)
Edit the cellForItemAt function:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: self.cell,
for: indexPath) as! MyCell
cell.bgImg.image = UIImage(named: "img.png")
cell.label1.text = "..."
cell.label2.text = "..."
return cell
Use the init function in the MyCell class to layout the labels.
Create Subclass of collection view cell and Instead of UICollectionViewCell use CustomCollectionViewCell
class CustomCollectionViewCell: UICollectionViewCell {
var imageView: UIImageView?
var label: UILabel?
override init(frame: CGRect) {
super.init(frame: frame)
imageView = UIImageView(frame: self.bounds)
//customise imageview
imageView?.backgroundColor = UIColor.red
contentView.addSubview(imageView!)
label = UILabel(frame: CGRect(x: 20, y: 20, width: self.bounds.width - 20, height: 20))
//Customsize label
label?.text = "Hello"
label?.textColor = UIColor.white
contentView.addSubview(label!)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var bounds: CGRect {
didSet {
contentView.frame = bounds
}
}
}
In View Controller updated following code:
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Vote"
collectionView?.backgroundColor = UIColor.white
collectionView?.register(CustomCollectionViewCell.self, forCellWithReuseIdentifier: cell)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: self.cell, for: indexPath) as! CustomCollectionViewCell
cell.backgroundColor = UIColor.lightGray
return cell
}

Swift - Draw lines between several random CGPoints

I am trying to create a simple line graph that should display the average monthly user score. So far I have created a collectionView with a white dot at the top of each cell, but now I would like to have a straight line between each dot. I have added a temporary array for testing purposes.
Since it will be variable server data (the last six months), the location of the dots can be different each time. What should I do to connect the first dot with the second one and the second one with the next one (until all dots are connected)?
User profile data controller
class UserProfileData: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var cellId = "cellId"
let values: [CGFloat] = [4.5, 3.2, 4.8, 5.0, 2.3, 2.9]
init() {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = UICollectionViewScrollDirection.horizontal
super.init(collectionViewLayout: layout)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView?.dataSource = self
self.collectionView?.delegate = self
collectionView?.backgroundColor = Constants.MAIN_THEME_COLOR
collectionView?.isScrollEnabled = false
collectionView?.register(BarCell.self, forCellWithReuseIdentifier: cellId)
}
// MARK: UICollectionViewDataSource
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return values.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 50, height: view.frame.height - 20)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! BarCell
if let max = values.max() {
let value = values[indexPath.item]
let ratio = value / max
cell.barHeightConstraint?.constant = view.frame.height * ratio
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 4, bottom: 0, right: 4)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
}
My custom cell
// Create custom cell(s)
class BarCell: UICollectionViewCell {
let barView: UIView = {
let view = UIView()
view.backgroundColor = .clear
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let barLabel: UILabel = {
let label = UILabel()
label.text = "."
label.textColor = .white
label.font = UIFont.systemFont(ofSize: 70)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
var barHeightConstraint: NSLayoutConstraint?
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(barView)
barView.addSubview(barLabel)
barHeightConstraint = barView.heightAnchor.constraint(equalToConstant: 300)
barHeightConstraint?.isActive = true
barHeightConstraint?.constant = 100
barView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
barView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
barView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
barLabel.centerXAnchor.constraint(equalTo: barView.centerXAnchor).isActive = true
barLabel.topAnchor.constraint(equalTo: barView.topAnchor, constant: 5).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
A UICollectionView has a backgroundView property. You should be able to set the backgroundView of your UICollectionView to a custom UIView that draws the lines between your items.

Swift collectionViewCells are not showing

I have got this Swift code
`
let cellId="cellId"
class FeedController: UICollectionViewController{
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Centill"
collectionView?.reloadData()
collectionView?.backgroundColor = UIColor(white: 0.95, alpha: 1)
collectionView?.register(FeedCell.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);
cell.backgroundColor = .yellow
return cell
}
}
class FeedCell: 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 = .yellow
}
}
`
But unfortunately my cells are not showing.It only shows navigation bar and background color.what may be the problem with my code?
Try This code:
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
layout.itemSize = CGSize(width: 60, height: 60)
let myCollectionView:UICollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
myCollectionView.dataSource = self
myCollectionView.delegate = self
myCollectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "MyCell")
myCollectionView.backgroundColor = UIColor.whiteColor()
self.view.addSubview(myCollectionView)
You have to provide the size for collection view cell. add the below code snippet
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// calculate and return the height
}
In your cellForItemAt dataSource method you need to give custom UICollectionCell Class
let cell=collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! FeedCell
cell.backgroundColor = .yellow
return cell
Then you will able to see cell.
Try it.
You add in the class
UICollectionViewDataSource and UICollectionVIewDelegate.

Adding WebView to CollectionView without using MainStoryboard

I've been working on CollectionView with ImageView in each cells. Now I'm wondering how to add WebView working the same way as ImageView. I want it working as an element in each cell, is it possible? In addition, I am not using storyboard.
import UIKit
class HomeController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Home"
collectionView?.backgroundColor = UIColor.white
collectionView?.register(WebCell.self, forCellWithReuseIdentifier: "cellId")
}
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: "cellId", for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: view.frame.height - 500)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
}
class WebCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
let StronaSzkolna: UIImageView = {
let webview = UIImageView()
webview.backgroundColor = UIColor.blue
webview.translatesAutoresizingMaskIntoConstraints = false
return webview
}()
func setupViews() {
addSubview(StronaSzkolna)
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-16-[v0]-16-|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":StronaSzkolna]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-16-[v0]-16-|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":StronaSzkolna]))
StronaSzkolna.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}