-1

I need to draw 5 different style of cell in a UITableView and i need a small help of you! I show you what i write in my ViewController:

var selfHeightCell : CGFloat? // for custom rowHeight

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.UITableView.estimatedRowHeight = 200.00;
    self.selfHeightCell = UITableViewAutomaticDimension;
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 10
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cardCell", for: indexPath) as! CardCell
    switch indexPath.row { // this is for test my code
    case 0:
        selfHeightCell = cell.workTest(drawCard: .verySmallCard)
    case 1:
        selfHeightCell = cell.workTest(drawCard: .smallCard)
    case 2:
        selfHeightCell = cell.workTest(drawCard: .mediumCard)
    case 3:
        selfHeightCell = cell.workTest(drawCard: .basiqCard)
    case 4:
        selfHeightCell = cell.workTest(drawCard: .bigCard)
    case 5:
        selfHeightCell = cell.workTest(drawCard: .mediumCard)
    case 6:
        selfHeightCell = cell.workTest(drawCard: .mediumCard)
    case 7:
        selfHeightCell = cell.workTest(drawCard: .basiqCard)
    case 8:
        selfHeightCell = cell.workTest(drawCard: .basiqCard)
    case 9:
        selfHeightCell = cell.workTest(drawCard: .basiqCard)
    default:
        selfHeightCell = cell.workTest(drawCard: .basiqCard)
    }
    return cell
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return selfHeightCell!
}

and now the code of my CardCell:

func workTest(drawCard: state) -> CGFloat{
    var heightOfCardRow : CGFloat = 0
    switch drawCard {
    case .verySmallCard:
        heightOfCardRow = self.drawCard(height : 60)
    case .smallCard:
        heightOfCardRow = self.drawCard(height : 100)
    case .mediumCard:
        heightOfCardRow = self.drawCard(height : 140)
    case .basiqCard:
        heightOfCardRow = self.drawCard(height : 200)
    case .bigCard:
        heightOfCardRow = self.drawCard(height : 280)
    }
    return heightOfCardRow
}

func drawCard(height : CGFloat) -> CGFloat{
    if(cardView.subviews.count == 0){
        self.addSubview(cardView)
        cardView.frame = CGRect(marginCardWidth,
                                marginCardHeight,
                                self.bounds.size.width - (marginCardWidth*2),
                                height - (marginCardHeight*2))
        cardView.layer.cornerRadius = 10
    }
    if(self.ShadowLayerCard == nil){
        let shadowLayer = CAShapeLayer()
        self.ShadowLayerCard = shadowLayer
        shadowLayer.path = UIBezierPath(roundedRect: cardView.bounds, cornerRadius: 10).cgPath
        shadowLayer.fillColor = UIColor(rgb: 0xffcc00).cgColor
        shadowLayer.shadowPath = shadowLayer.path
        shadowLayer.shadowColor = UIColor.black.cgColor
        shadowLayer.shadowRadius = 5
        shadowLayer.shadowOpacity = 0.2
        shadowLayer.shadowOffset = CGSize(width: 0, height: 0)
        cardView.layer.insertSublayer(shadowLayer, at: 0)
    }
    return cardView.bounds.size.height + (marginCardHeight*2)
}

I show you a picture of the simulator:

Sorry for all the code but it necessary I think to solve my problem. I think the error is because i draw programmatically or I custom the height of the cell in a wrong way!

My question is: What are the bad ways that give these problems?

Daphyduck
  • 127
  • 1
  • 10
  • So many wrong thing in your code, `UITableViewAutomaticDimension ` require constraints, `heightForRowAt ` get called before `cellForRowAt ` so override height here is wrong, `cardView ` can be created in storyboard or use constraint, theres only needing of 1 cell type,.... – Tj3n Jul 23 '18 at 07:43
  • @Tj3n Ok, for modified my cardView I edit the constraint of the height in the CardCell class after add this one in the storyboard ? because after I add the card i need to add several button UIImageView and other components programmatically depending of the card state enum – Daphyduck Jul 23 '18 at 07:48

1 Answers1

1

When using dynamic cell height don't implement heightForRowAt , but either leave the contentView to layout itself based on it's content , or give it a height constraint and change it in cellForRowAt

Consider that cell class

class MyCell : UITableViewCell {

    let redView = UIView()

    var redViewHCon:NSLayoutConstraint!

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        redView.translatesAutoresizingMaskIntoConstraints = false

        self.contentView.addSubview(redView)

        redView.backgroundColor = .red

        NSLayoutConstraint.activate( [

            redView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 20),

            redView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 0),

            redView.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: 0),

            redView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -20)

            ])

        redViewHCon =  redView.heightAnchor.constraint(equalToConstant: 300)

        redViewHCon.isActive = true

    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

//

In cellForRowAt

let cell = tableView.dequeueReusableCell(withIdentifier:"pp") as! MyCell 
cell.redViewHCon.constant = CGFloat((indexPath.row + 1) * 100)

//

add this line in viewDidLoad

 tableView.register(MyCell.self, forCellReuseIdentifier: <#setIdentifier#>)

enter image description here

Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
  • Thanks for your reply, but i draw the card programmatically, how "leave the contentView to layout itself based on it's content" please ? – Daphyduck Jul 23 '18 at 08:01
  • when you add elements to it hook the constraints properly from top to bottom , then it will stretch according to content without any constants but this for intrinsic elements like the label and the button if you add a view say between them then you should define a height for it – Shehata Gamal Jul 23 '18 at 08:02
  • I'm sorry but I don't anderstand what i need to do, for begin I delete my heightForRowAt function this is a bad idea, but i need to add programmatically the constraint of the cardView that's it ? – Daphyduck Jul 23 '18 at 08:21
  • I just have a problem when iI Init my custom cell. I have this error `Fatal error: init(coder:) has not been implemented`. I use your code – Daphyduck Jul 23 '18 at 09:32
  • I use storyboard. And register what ? – Daphyduck Jul 23 '18 at 09:43
  • Ok, this work, i have a visual but now I have several error of constraint like this `Unable to simultaneously satisfy constraints` when i scroll up and down. So I give you the pastebin of the error: https://pastebin.com/VwEcLfYB ... Thanks for your big help – Daphyduck Jul 23 '18 at 09:56
  • set the priority of the bottom constraint of the redView to 999 , you make get it out of activate like the height to change that – Shehata Gamal Jul 23 '18 at 09:57
  • Ok thanks, and how change this priority of this constraint : bottomAnchor ? – Daphyduck Jul 23 '18 at 10:03
  • Ok it's good, Thanks! I write : `let bottomAnchor = cardView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -6) bottomAnchor.priority = UILayoutPriority(rawValue: 999) bottomAnchor.isActive = true` – Daphyduck Jul 23 '18 at 11:40