SteffenK
SteffenK

Reputation: 712

Custom Table View Cell Drawing Wrong Height When Scrolling

I'm customizing my table view cell inside the willDisplayCell method. For some reason it is drawing some subviews with the wrong height while scrolling (see video). I can't figure out why...

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {

    cell.contentView.backgroundColor=UIColor.clearColor()
    cell.reloadInputViews()

    let height = cell.frame.height - 15

    var whiteRoundedCornerView:UIView!
    whiteRoundedCornerView=UIView(frame: CGRectMake(7,10,self.view.bounds.width-14,height))
    whiteRoundedCornerView.backgroundColor=getColorByID(colorID!)
    whiteRoundedCornerView.layer.masksToBounds=false

    whiteRoundedCornerView.layer.shadowOpacity = 1.55;

    whiteRoundedCornerView.layer.shadowOffset = CGSizeMake(1, 0);
    whiteRoundedCornerView.layer.shadowColor=UIColor.grayColor().CGColor

    whiteRoundedCornerView.layer.cornerRadius=5.0
    whiteRoundedCornerView.layer.shadowOffset=CGSizeMake(-1, -1)
    whiteRoundedCornerView.layer.shadowOpacity=0.5

    whiteRoundedCornerView.layer.shouldRasterize = true
    whiteRoundedCornerView.layer.rasterizationScale = UIScreen.mainScreen().scale


    if cell.contentView.subviews.count < 6 {  //  to avoid multible subview adding when scrolling...

        cell.contentView.addSubview(whiteRoundedCornerView)
        cell.contentView.sendSubviewToBack(whiteRoundedCornerView)

    }
}

Here is a video of the issue:

https://vid.me/QeV0

Update:

I also tried to move the code to layoutSubviews but still the same issue...

override func layoutSubviews() {
    super.layoutSubviews()

    let height = self.frame.height - 15

    var whiteRoundedCornerView:UIView!
    whiteRoundedCornerView=UIView(frame: CGRectMake(7,10,UIScreen.mainScreen().bounds.width-14,height))
    whiteRoundedCornerView.backgroundColor=UIColor.greenColor()//getColorByID(colorID!)
    whiteRoundedCornerView.layer.masksToBounds=false

    whiteRoundedCornerView.layer.shadowOpacity = 1.55;

    whiteRoundedCornerView.layer.shadowOffset = CGSizeMake(1, 0);
    whiteRoundedCornerView.layer.shadowColor=UIColor.grayColor().CGColor

    whiteRoundedCornerView.layer.cornerRadius=5.0
    whiteRoundedCornerView.layer.shadowOffset=CGSizeMake(-1, -1)
    whiteRoundedCornerView.layer.shadowOpacity=0.5

    whiteRoundedCornerView.layer.shouldRasterize = true
    whiteRoundedCornerView.layer.rasterizationScale = UIScreen.mainScreen().scale


    if self.contentView.subviews.count < 6 {              

        self.contentView.addSubview(whiteRoundedCornerView)
        self.contentView.sendSubviewToBack(whiteRoundedCornerView)

    }
}

If i don't check the tableview.subviews.count it will add tons of subviews to the cell while scrolling.

I want to change the height of the existing subview when the cell is reused.

Upvotes: 2

Views: 1212

Answers (2)

fluidsonic
fluidsonic

Reputation: 4676

You have a check to not add the subviews multiple times. When that case happens you already have added the subviews earlier but their height may now be wrong and you must update them.

UITableView reuses cells so a new cell with different height might already contain your subviews but with the wrong height since you don't update it.

You should cleanly separate the set-up of your subview and the layout like so:

class MyCell: UITableViewCell {

    private let whiteRoundedCornerView = UIView()


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

        setUp()
    }


    required init?(coder: NSCoder) {
        super.init(coder: coder)

        setUp()
    }


    override func layoutSubviews() {
        super.layoutSubviews()

        let bounds = self.bounds

        var whiteRoundedCornerViewFrame = CGRect()
        whiteRoundedCornerViewFrame.origin.x = 7
        whiteRoundedCornerViewFrame.origin.y = 10
        whiteRoundedCornerViewFrame.size.width = bounds.width - 7 - whiteRoundedCornerViewFrame.origin.x
        whiteRoundedCornerViewFrame.size.height = bounds.height - 5 - whiteRoundedCornerViewFrame.origin.y
        whiteRoundedCornerView.frame = whiteRoundedCornerViewFrame
    }


    private func setUp() {
        setUpWhiteRoundedCornerView()
    }


    private func setUpWhiteRoundedCornerView() {
        let child = whiteRoundedCornerView
        child.backgroundColor = .greenColor()

        let layer = child.layer
        layer.cornerRadius = 5.0
        layer.rasterizationScale = UIScreen.mainScreen().scale
        layer.shadowColor = UIColor.grayColor().CGColor
        layer.shadowOffset = CGSize(width: -1, height: -1)
        layer.shadowOpacity = 0.5
        layer.shouldRasterize = true

        insertSubview(child, atIndex: 0)
    }
}

Upvotes: 1

Mohit Mathur
Mohit Mathur

Reputation: 62

If the data on different rows is of different size then you have to set the height of the tableview cell dynamically

Here is the code:

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat{

    var height:CGFloat

    let constraint1:CGSize = CGSizeMake(self.view.frame.size.width/2-70, 5000.0)
    let string="eefdgvfgfhgfgfhgfgjhidffjo;dkfnkjfldjfkjfkjfldfjkkjhbkjflfjihkfjkfjgfkjfkgfkgjlfgnfjgnfgnfgbkgmfjgfkgjfkggjlfgklkgkgkglkgggfkglgkkgjlgkgk"

    let answerSize = string.boundingRectWithSize(constraint1, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: UIFont.systemFontOfSize(17.0)], context: nil)
    let questionSize = string.boundingRectWithSize(constraint1, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: UIFont.systemFontOfSize(17.0)], context: nil)   

    height=answerSize.height + questionSize.height

    return height
}

Upvotes: 0

Related Questions