Search code examples
iosswiftuiviewuiscrollviewuikit

Swift: Make vertical scrolling feed with programmatically sized UIViews


I'm building a scrolling feed in my app with data grabbed from a database (firebase). I'm not very experienced in Swift as most of the stuff I do is web design. What I'm looking for is a good way to size the height of my UIViews. Here is what I currently have (fixed height): enter image description here

Here's my code UIView class:

class eventView: UIView {

    let eventDate : UILabel = {
        let eventDate = UILabel()
        eventDate.translatesAutoresizingMaskIntoConstraints = false
        eventDate.numberOfLines = 0
        eventDate.textAlignment = .center
        return eventDate
    }()
    let eventTitle : UILabel = {
    Same thing as eventDate
    }()
    let eventDesc : UILabel = {
    same thing as eventDate
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = UIColor.lightGray
        self.layer.cornerRadius = 10
        self.addSubview(eventDate)
        eventDate.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
        eventDate.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
        self.addSubview(eventTitle)
        eventTitle.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
        eventTitle.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
        eventTitle.topAnchor.constraint(equalTo: eventDate.bottomAnchor).isActive = true

        self.addSubview(eventDesc)
        eventDesc.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
        eventDesc.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
        eventDesc.topAnchor.constraint(equalTo: eventTitle.bottomAnchor).isActive = true
    }

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

Here is my for list that displays these UIViews:

    var i = 0
    for data in self.eventViewData {
        let view = eventView(frame: CGRect(x: 0, y: ( CGFloat(170 * i)), width: self.scrollView.frame.width - 20, height: CGFloat(150)))
        view.center.x = self.scrollView.center.x
        view.eventDate.text = data.date
        view.eventTitle.text = data.title
        view.eventDesc.text = data.description
        self.scrollView.addSubview(view)

        i += 1
    }

I usually am using HTML div's and such so I'm having a hard time figuring out how to style these. Any information or links to tutorials on how to programmatically adjust constraints to the UILabels in my eventViews are also appreciated.


Solution

  • How to calculate the desired height seems to be the question. While there are a lot of ways to do this one approach would be something like this:

        func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat{
            let label:UILabel = UILabel(frame: CGRectMake(0, 0, width, CGFloat.greatestFiniteMagnitude))
            label.numberOfLines = 0
            label.lineBreakMode = NSLineBreakMode.byWordWrapping
            label.font = font
            label.text = text
            label.sizeToFit()
            return label.frame.height
    }
    
        let font = UIFont(name: "Helvetica", size: 20.0)
        var height = heightForView("This is just a load of text", font: font, width: 100.0)
        // apply height to desired view
    

    I prefer to put the heightForView function in an extension myself but it isn't required.