How to size a UIStackView depending on its content?

22,396

Solution 1

UIStackView is designed to grow its size according to the content. In order for that to work, you need to set up the constraints between the UIStackView and the UITableViewCell. For example, this is how the constraints look like in interface builder:

enter image description here enter image description here

If you like setting up constraints in code, that should work too.

To demonstrate that this will work, I have this for the cellForRowAt function. Basically, it puts a number of UILabel inside the UIStackView and the label count is depending on the row number.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "TableviewCell", for: indexPath) as! TableviewCell
    for i in 1...indexPath.row + 1 {
        let label = UILabel()
        label.text = "Row \(indexPath.row), Label \(i)"
        cell.stackView.addArrangedSubview(label)
    }
    return cell
}

Here is the final result:

https://github.com/yzhong52/AutosizeStackview

Solution 2

I built this example I hope it helps, I've created a tableView which use a cell that contains a stackView and the views loaded in the stackView are gotten from a nib file

https://github.com/Joule87/stackView-within-TableViewCell

Share:
22,396
Stéphane de Luca
Author by

Stéphane de Luca

My passion is to quickly materialize ideas: one of my latest pet project is ”Gas Discount” ⛽️ to get 20% off on your gas (https://apps.apple.com/nl/app/carburant-discount/id1465235480) (Swift) Released v1 @ xmas 2019 (ads+freemium model). Writing v2 in Dart/Flutter for early 2022. Currently, and since 2019: VP digital, CTO & CPO at Olenergies (🔋 LiFP connected batteries) where I develop anEMS IoT ecosystem from crash that comprises — 1) an IoT platform that connects DERs and optimizes the energy of thousands batteries across the world (Azure / MongoDB / TSI / InfluxDB / PostgreSQL / MERN / GraphQL / Docker / WSS / MQTT / IoT Hub / DPS) — 2) a Linux-based smart controller (Beaglebone / NodeJS) and custom ESP32 PCB (ESP32 / CPP / FreeRTOS) that connects to batteries BMS (thru CANbus & RS485) and charger/inverter (thru MODbus). w/ automatic updates and — 3) an iOS + Android BLE app to control the control everything (Flutter 2 / Dart). 2014 - 2016: CTO / CPO at Presstalis/ZEENS. I created a brand new B2C digital press service that exposes all journals & mags published in France since 1947 via an all-you-can-eat subscription-based model on iPad (See video here https://stephanedeluca.com/zeens.php). I also designed and developed mobile-to-store and digital newsstand apps which includes social networking and bringing innovative BM to the press industry (50 % discount on mags) + in-store purchase of journals & show tickets in partnership with Ville de Paris, JCDecaux, Mediakiosk, FNAC/France Billet, Logista and Presstalis) 2009 - 2014: member of the Executive Committee of the RIAM government funding organisation (CNC/OSEO): financing of innovative projects in the movie and computer-related industries at large (11M€/year). 2010 - 2014: VP Products and CTO at LeKiosque.fr, focused on the digital magazine distribution where I designed the first ever 3D newsstand for iPad, ranking #1 grossing app for iPad in France with more 1.5M downloads! 2009 - 2010, acted as COO for Mimesis Republic and industrialized the production (MMO/social network & apps). In 2009, I published Santa-Claus for iPhone on AppStore, introducing for the 1st time the 3D parallax effect since natively integrated by Apple in iOS! 2007 - 2009, I was the MobiLuck.com CTO (geolocalized social network for mobiles). This LBS friends finder service displays 35M pages/month and has attracted more than 1.2M users (Q2 2009) since its launch in August 2007 and currently recruits an average of 5K users per day as per the current trend and we see our traffic doubling every quarter! From 2003, I was the In-Fusio Advanced Technology Manager where I created mobile phone massive cross-platform multi-player technology & service. Before, I've been in the video game industry for 10y where I successively developed titles, created & sold realtime 3D technologies & finally took in charge a business unit of Kalisto (IPO in 1999) Get in touch @ +33 6 13 510 966 / [email protected]

Updated on July 09, 2022

Comments

  • Stéphane de Luca
    Stéphane de Luca almost 2 years

    I would like to have a similar behavior than the <Table> HTML tag, in the sense where the frame is sized according to its content.

    In my very context, I use an UIStackView as the content view of a UITableViewCell. As items in the cell are various information, the resulting height of the cell should be variable.

    My strategy is to programmatically build a cell as a UIStackView with a .Vertical axis, as in the code snippet as follows:

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
    
        let sv = UIStackView(frame: tableview.frame)
        sv.axis = .Vertical
        cell.addSubview(sv)
        for i in information {
            let l = UILabel()
            l.text = i
            sv.addSubViewAndArrange(l)
        }
    
        return cell
    }
    

    Unfortunately, the cell size does not adjust to the content, and as a result I have to set the cell height myself, as follows:

    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return cellHeight     // a constant
    }
    

    How could I fix that?