custom UICollectionViewCell class recognize but not working - swift

I implemented a custom class for my collectionview cells.
The class recognize the attributes like labels but when i run my app the label text doesn't display.
Class is register like this :
self.collectionView!.registerClass(StatsCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
here is the init method of the custom cell class:
var textlabel = UILabel()
override init(frame: CGRect) {
let width = frame.size.width
let height = frame.size.height
textlabel = UILabel(frame: CGRectMake(0, 0, width,height))
super.init(frame: frame)
}
and the implementation :
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! StatsCollectionViewCell
// Configure the cell
cell.textlabel.text = "test"
return cell
}
Could someone point me to my mistake please, i'm a bit lost here, cannot see what's wrong.
Note that i can use the cell properties (meaning the cell is in fact here).

You didn't put textlabel in a view.
override init(frame: CGRect) {
let width = frame.size.width
let height = frame.size.height
textlabel = UILabel(frame: CGRectMake(0, 0, width,height))
super.init(frame: frame)
addSubview(textlabel) // add text label to view
}

Related

How can I use scrollView inside collectionViewCell with dynamic size

I want to create this page. And I created a collectionView inside viewController. But how can I make the height of this dynamic and i think i need to create a scroll view? How do I change the collection view size than json data loaded? And how should the structure on this page?
I created programmatically collection view but I don't have any data now. But when I create collection view I have to give height value. I must when I loaded json data than I will set frame details. Please help this topics.. At least give mind please.. Thank you all
Edit:
I added scroll view inside cell but switch between cells not working now. In red area(cell) working switching but not working on containerView..
Scroll View problem
class NewsDetailController: UIViewController {
private lazy var collectionView: UICollectionView = {
let frame = CGRect(x: 0, y: 100, width: view.frame.width, height: 800)
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let cv = UICollectionView(frame: frame, collectionViewLayout: layout)
cv.isPagingEnabled = true
cv.delegate = self
cv.dataSource = self
cv.showsHorizontalScrollIndicator = false
cv.register(NewsDetailCell.self, forCellWithReuseIdentifier: reuseIdentifier)
return cv
}()
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
}
// MARK: - Helpers
func configureUI() {
view.addSubview(collectionView)
view.backgroundColor = .white
view.addSubview(stackBottomButtons)
stackBottomButtons.anchor(left: view.leftAnchor,bottom: view.bottomAnchor,right: view.rightAnchor,paddingLeft: 16,paddingBottom: 32,paddingRight: 16, height: 60)
backButton.widthAnchor.constraint(equalToConstant: 100).isActive = true
shareButton.widthAnchor.constraint(equalToConstant: 100).isActive = true
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! NewsDetailCell
return cell
}
}
extension NewsDetailController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: 800)
}
}
class NewsDetailCell: UICollectionViewCell {
// MARK: - Properties
let contentLabel: UILabel = {
let label = UILabel(frame: CGRect.zero)
label.numberOfLines = 0
return label
}()
// MARK: - Lifecycle
override init(frame: CGRect) {
super.init(frame: frame)
configure()
configureUI()
}
func configure() {
contentLabel.text = articleViewModel?.article.content
}
func configureUI() {
addSubview(contentLabel)
contentLabel.anchor(top: stack.bottomAnchor,left: leftAnchor,right: rightAnchor)
}
}
I want to make this page.
Full Code
I think you are looking for something like this
To make the frame size dynamic you you need to set the cell size by the attributes combined height inside of the cells this can be done in the customCell file you create using this link

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
}

Reusable UICollectionViewCell not changing UIImageView property (showing duplicates)

I have a UICollectionView with a reusable cell that contains a UIImageView but the collection view displays the same image in the image view for each cell item in the collection.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let path = indexPath.item
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "friendAvatar", for: indexPath) as! AvatarCollectionViewCell
cell.avatarView.image = friends[path].userAvatar
return cell
}
class AvatarCollectionViewCell: UICollectionViewCell {
var avatarView = UIImageView()
override init(frame: CGRect) {
super.init(frame: frame)
prepareForReuse()
config()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func prepareForReuse() {
avatarView.image = nil
avatarView.removeFromSuperview()
}
func config() {
avatarView.frame = CGRect(x: 0, y: 0, width: 64, height: 64)
avatarView.layer.cornerRadius = 64 / 4
avatarView.clipsToBounds = true
avatarView.contentMode = .scaleAspectFill
addSubview(avatarView)
}
}
First of all, you are removing the image view from its superview in prepareForReuse() but you never add it back. init() will not be called when reusing a cell, and neither will config(). Unless you have a specific reason for it, you shouldn't need to remove the image view from its superview. Just setting its image to nil should be enough.
Also, set a breakpoint and verify that friends[path].userAvatar returns a valid path to an image.

UITableViewCell with a UIView subclass creates multiple layers on cell

I have an custom UITableViewCell created with (.xib) and have UIView subclass instance inside cell created from code
table delegate method :
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomCellOne", forIndexPath: indexPath) as! CustomOneCell
let woView = ModuleView(frame: CGRect(x: 10, y: 10, width: 400, height: 400))
woView.addBehavior(self.modulesForSubjects[indexPath.row])
// remove subviews
for subview in cell.subviews{
subview.removeFromSuperview();
}
// then add your view
cell.wiView = woView
return cell
}
my full UIView subclass :
class ModuleView: UIView {
override init (frame : CGRect) {
super.init(frame : frame)
}
convenience init () {
self.init(frame:CGRect.zero)
}
required init(coder aDecoder: NSCoder) {
fatalError("This class does not support NSCoding")
}
func addBehavior (ArrayOfmodulesForSubject: [SubjectsModules]) {
var number :CGFloat = 30
var number2 :CGFloat = 30
print(ArrayOfmodulesForSubject.count)
for (i, index) in ArrayOfmodulesForSubject.enumerate() {
let yourLabel1 = UILabel(frame: CGRectMake(number, 40 , 35 , 30))
let yourLabel2 = UILabel(frame: CGRectMake(number2, 60 , 140 , 30))
yourLabel1.textColor = UIColor.whiteColor()
yourLabel1.backgroundColor = UIColor.redColor()
yourLabel1.text = String(index.score)
yourLabel2.textColor = UIColor.whiteColor()
yourLabel2.backgroundColor = UIColor.blackColor()
yourLabel2.text = index.date
self.addSubview(yourLabel1)
self.addSubview(yourLabel2)
number += 30
number2 += 70
}
}
here is what i get after some scrolling:
UPDATE rnsjtngus solution, unfortunately also didn't helped (maybe im doing something wrong)
class CustomOneCell: UITableViewCell {
var arr = [SubjectsModules]()
#IBOutlet weak var wiView: ModuleView!
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?){
// Initialize your custom cell
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.setupWoView(self.arr)
}
override func awakeFromNib() {
print("AWAKED FROM NIB")
for subview in subviews{
subview.removeFromSuperview()
if superview != nil {
superview!.removeFromSuperview()
}
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func setupWoView(arrayOfmodulesForSubject: [SubjectsModules]) {
let woView = ModuleView(frame: CGRect(x: 10, y: 10, width: 400, height: 400))
woView.backgroundColor = UIColor.blueColor()
self.addSubview(woView)
}
}
Simple but, bad solution is
just remove subviews from cell before you add your own view
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomCellOne", forIndexPath: indexPath) as! CustomOneCell
let woView = ModuleView(frame: CGRect(x: 10, y: 10, width: 400, height: 400))
woView.addBehavior(self.modulesForSubjects[indexPath.row])
// remove subviews
for subview in cell.subviews{
subview.removeFromSuperview();
}
// then add your view
cell.addSubview(woView)
return cell
}
When you call dequeue the method dequeues an existing cell if one is available or creates a new one using the class or nib if not.
This means you may well get one that has already had a subview added to it and when you dequeue it again your code would then add a second one. You need to start by removing any existing subviews.

Why can't I change custom view background in cell of UICollectionView

I have a UICollectionView and a custom UICollectionViewCell.
The UICollectionViewCell contains a custom UIView.
I need to change the color of the UIView according to a property in my array.
I have created the custom UIView in the storyboard, assigned appropriate class to it and even a tag.
I am trying to change the color of the my custom circleView in cellForItemAtIndexPath
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
var cell = collectionView.dequeueReusableCellWithReuseIdentifier("circleCell", forIndexPath: indexPath) as! BRGameCollectionViewCell
var circle = BRGameManager.sharedInstance.gameArray[indexPath.section][indexPath.row] as BRCircle!
cell.circleView.circleColor = UIColor.redColor()
return cell
}
I have tried it even with getting the circleView via tag but it doesn't work either.
What Am I doing wrong?
My custom view Class looks like this:
class BRCircleView: UIView {
var circleSize : CGFloat = 10
var circleColor : UIColor!
override init(frame: CGRect) {
if( frame == CGRectZero){
var newFrame = CGRectMake(0, 0, self.circleSize, self.circleSize)
}
self.circleColor = UIColor(rgba: GlobalConstants.colors.hexColorGreen)
super.init(frame: frame)
}
convenience init(frame: CGRect, circleColor : UIColor){
self.init(frame: frame)
self.circleColor = circleColor
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func drawRect(rect: CGRect) {
self.layer.cornerRadius = self.frame.size.width/2
self.clipsToBounds = true
self.backgroundColor = self.circleColor
}
}
If you want to reflect your circleView's background color change,you need to redraw your view's content.Use setNeedsDisplay method of UIView would do this trick.More about setNeedsDisplay
So before returning cell, add this line of code.
...
cell.circleView.circleColor = UIColor.redColor()
cell.circleView.setNeedsDisplay() // add this line.
return cell