0

My UIView's are stacking up on top of each other like so :

enter image description here

Each UIView is inside a wordContainer. Each UIView has two UILabel's inside of it

I create each individual UIView with two child UILabel's like so :

    var labels = [UIView]()
    for word in words {

        let wordLabel               = UILabel(frame: CGRectZero)
        wordLabel.text              = word.valueForKey("sanskrit") as? String
        wordLabel.numberOfLines     = 0
        wordLabel.sizeToFit()
        wordLabel.translatesAutoresizingMaskIntoConstraints = false

        let englishWordLabel           = UILabel(frame: CGRectMake(wordLabel.frame.width + 10,0,0,0))
        englishWordLabel.text          = word.valueForKey("english") as? String)
        englishWordLabel.numberOfLines = 0
        englishWordLabel.sizeToFit()
        englishWordLabel.lineBreakMode     = .ByWordWrapping
        englishWordLabel.translatesAutoresizingMaskIntoConstraints = false

        let wordView = UIView(frame: CGRectMake(0,0,self.view.frame.width,englishWordLabel.frame.height))
        wordView.translatesAutoresizingMaskIntoConstraints = false
        wordView.addSubview(wordLabel)
        wordView.addSubview(englishWordLabel)

        wordView.sizeToFit()

        labels.append(wordView)
    }

Then I take this collection of UIView's and add them to my wordContainer. This is the part, where I imagine, I should be setting NSLayoutConstraints. The idea is that I want them all to stack up on top of each other properly. For example, it should look like this :

word: definition
word: definition
word: definition
word: definition

But instead it looks like this :

enter image description here

I add them into the wordContainer like so :

    let wordContainer  = UIView(frame: CGRectZero)

    var currentY:CGFloat      = 0.0
    let margin_height:CGFloat = 4.0
    var height:CGFloat        = 0

    for view in wordViews {
        var rect = view.frame
        rect.origin.y = currentY
        view.frame = rect

        currentY += view.frame.height
        height += view.frame.height

        wordContainer.addSubview(view)

    }
    let containRect = CGRectMake(0,0,self.view.frame.width, height)
    wordContainer.frame = containRect

And then I set my constraints for the wordContainer which effectually allows the space for all the words to exist if they weren't piled on top of each other :

   wordContainer.bottomAnchor.constraintEqualToAnchor(cell.contentView.bottomAnchor).active     = true
   wordContainer.topAnchor.constraintEqualToAnchor(cell.contentView.topAnchor).active           = true

My latest idea is that maybe I should be adding constraints to this. I have experimented with adding NSLayoutConstraints to the height of the cell, and when I do all the words no longer are appropriately laid out. Instead, they are stacked on top of each other. But this seems like the right direction..

Trip
  • 26,756
  • 46
  • 158
  • 277
  • 2
    You can't use `UITableViewAutomaticDimension` without using autolayout – dan Apr 05 '16 at 22:11
  • @dan by autolayout, are you referring to IB Visual? – Trip Apr 06 '16 at 14:38
  • By autolayout I mean adding constraints to the views. You should really just use a `UIStackView` for this rather than trying to manually stack your views by settings frames – dan Apr 06 '16 at 15:37

2 Answers2

2

In order for the cell to adjust its height automatically your content inside the contentView must have constraints against all 4 edges of the contentView.

I have just done this myself with different cell types for text, images and embedded tweets and had some of the issues you've described. I found the easiest way was to add a view around any components within the content view and then you can easily add the constraints to that element all around.

I've just had a quick look around for something that can demonstrate this and found another SO answer that explains it with a few screenshots.

Also the reference I used when doing this today was This post on Ray Wenderlich's site

Community
  • 1
  • 1
Scriptable
  • 19,402
  • 5
  • 56
  • 72
  • Thanks for writing. I've spent some time on that specific SO post yesterday. Copied it's code into mine, and by stretching the constraints for the `wordContainer` to its parent `cell` -- I see that the `cell.frame.size.height` does in fact change, but the cell still opens at `44.0`, and the subviews lose their spacing and stack on top of each other. – Trip Apr 05 '16 at 22:21
  • Your settings look fine above, it's just your constraints. You shouldn't need to set any heights as that will be calculated based on content, but you will need to set the distance between the top label and the top of the content view. The top of the second label and the bottom of the top label, and then the bottom of the second label and bottom of the content view. (And the sides) – Scriptable Apr 05 '16 at 22:32
  • Ah ok interesting. By "distance", do you mean set the constraints or the height/width? – Trip Apr 06 '16 at 08:01
  • margin space between elements, so like bottomLabel.top should be 10px from topLabel.bottom – Scriptable Apr 06 '16 at 08:55
  • I renovated my question above. Definitely think I'm almost there now. I added a constraint to to my `wordContainer` where the bottom and top anchor reflected the contentView of the cell. That definitely opened up the space correctly. but now the words stack on top of one another. would you know what constraints would be required to space them properly? thanks so much!! – Trip Apr 06 '16 at 14:49
  • have you set the number of lines and word wrapping properties? – Scriptable Apr 06 '16 at 14:59
  • Yes sir. On all the UILabel's that is. It's not so much an issue of the text wrapper per se -- but more that each UIView is stacking it's self one on top of the other. I even explicitly set the Y for each one, but they still go for the 0,0 no matter what. – Trip Apr 06 '16 at 15:08
  • oh you have a bunch of seperate words, the autolayout I have done is just one string. I see what your doing now. This will certaintly complicate matters. You should of really created a new question for this part as we've already resolved the previous issue and the comments and recommendations wont be relevant anymore. is there a reason you want to display them this way? how come you are doing this in a single cell? a tableview itself would likely be a better solution, each row could have a label on the left and one on the right for the definition – Scriptable Apr 06 '16 at 15:18
  • Ah good point. It would a tableView inside of a tableView. I should probably make a new file for another tableView, and include that. – Trip Apr 06 '16 at 15:51
  • Thanks for your help.. I should just make a new question. You definitely helped solve this with your answer. – Trip Apr 06 '16 at 15:53
0

In your UITableViewController, in viewDidLoad() , try:

//set up table view cell dynamic height
tableView.rowHeight = UITableViewAutomaticDimension

In the Storyboard, make sure you use AutoLayout and that all of the constraints of your cell's elements to the superview are set and fixed. For example, the top text of your cell must have its margin to Superview defined and set to a value.

firepod
  • 66
  • 7