Programmatically add subviews to a UIStackView

16,116

As Dan said in the comments, use addArrangedSubview to add a subview that will be automatically laid out by UIStackView.

Note, however: if you remove a view from the arrangedSubviews array on UIStackView, it is still a subview. From the UIStackView documentation:

The stack view ensures that its arrangedSubviews property is always a subset of its subviews property. Specifically, the stack view enforces the following rules:

• When the stack view adds a view to its arrangedSubviews array, it also add that view as a subview, if it isn’t already.

• When a subview is removed from the stack view, the stack view also removes it from the arrangedSubviews array.

• Removing a view from the arrangedSubviews array does not remove it as a subview. The stack view no longer manages the view’s size and position, but the view is still part of the view hierarchy, and is rendered on screen if it is visible.

It's always a good idea to start with the documentation.

Share:
16,116
kcstricks
Author by

kcstricks

Updated on June 19, 2022

Comments

  • kcstricks
    kcstricks almost 2 years

    I'm trying to implement a table view cell that displays a series of icons that represent home amenities (e.g. towels, wifi, laundry, etc.). The cell could potentially display a large number of amenities (depending on how many the home has), so I'll display a maximum of three and indicate that you can view more by clicking on the cell if there are more than three. Here is what it should look like (from Airbnb's app):

    enter image description here

    I am trying to do this by dynamically adding UIImageViews to a UIStackView in the table view cell. I am using a UIStackView with alignment set to "Fill" and distribution set to "Equal spacing", the idea being that the stack view will evenly space out the icons no matter how many I add to it.

    I set up the stack view in Storyboard. It has constraints to the top, bottom, left, and right margins of its content view, so that it fills the table view cell, up to the margins.

    Here is the code I am using to try to dynamically add UIImageViews to the cell. Note amenities is an array of strings equal to the names of the icons in my image assets folder:

            cell.stackView.backgroundColor = UIColor.greenColor()
            var i = 0
            while (i < amenities.count && i < 4) {
                if (i < 3) {
                    let imageView = UIImageView(image: UIImage(named: amenities[i]))
                    imageView.contentMode = .ScaleAspectFit
                    imageView.translatesAutoresizingMaskIntoConstraints = false
                    imageView.backgroundColor = UIColor.blueColor()
    
                    // Add size constraints to the image view
                    let widthCst = NSLayoutConstraint(item: imageView, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 50)
                    imageView.addConstraint(widthCst)
    
                    // Add image view to stack view
                    cell.stackView.addSubview(imageView)
                } else {
                    // Add a label to the stack view if there are more than three amenities
                    let label = UILabel()
                    label.text = "\(amens.count - i) more"
                    label.textAlignment = NSTextAlignment.Left
                    cell.stackView.addSubview(label)
                }
                i++
            }
    

    The backgrounds of the image views are blue, and the background color of the stack view is green. Here is the result, for a case where the house has three amenities:

    enter image description here

    Looks like all the image views are being pushed on top of one another to the left of the screen. They also fill the cell's content view from top to bottom, even though the stack view is pinned to the content view margins. There's no green in sight so it appears the stack view is not remaining pinned to the margins of the cell.

    Any idea what's wrong here?

  • rob mayoff
    rob mayoff about 8 years
    Also worth noting from the documentation: “The UIStackView is a nonrendering subclass of UIView. It does not provide any user interface of its own. Instead, it just manages the position and size of its arranged views. As a result, some properties (like backgroundColor) have no affect on the stack view. ” This is why kcstricks doesn't see her green background.
  • Alex Popov
    Alex Popov about 8 years
    Thanks @robmayoff! I actually didn't get that far in the docs. Shame on me!
  • kcstricks
    kcstricks about 8 years
    My apologies for the delayed response! I finally had the time to get back to the app and try this out. Worked perfectly! Thank you! Thanks to @robmayoff as well for the useful note.