1

I'm trying to add profile icons via UIImageViews to a UIStackView in order to keep the icons centered in a view. How would I go about adding UIImageViews of a fixed frame to a UIStackView and keep the UIStackView centered in the main view according to varying numbers of UIImageViews in the UIStackView?

let memberIcons: UIStackView = {
    let iconView = UIStackView()
    iconView.translatesAutoresizingMaskIntoConstraints = false
    iconView.axis = .horizontal
    iconView.spacing = 5
    iconView.distribution = .equalSpacing
    iconView.alignment = .center
    return iconView
}()

for member in story!.members {
            let circle = UIImageView()
            circle.frame = CGRect(x: 0, y: 0, width: 36, height: 36)
            circle.translatesAutoresizingMaskIntoConstraints = false
            circle.layer.cornerRadius = CGFloat(circle.frame.width / 2)
            circle.image = member.profilePicture
            circle.contentMode = .scaleAspectFill
            circle.clipsToBounds = true
            memberIcons.addArrangedSubview(circle)
        }
Explorer
  • 65
  • 1
  • 12

1 Answers1

0

Because you set memberIcons.distribution = .equalSpace, the stack view will ask its subviews for their intrinsic sizes. When asked, the UIImage (i.e. circle) will calculate its intrinsic size as "image pixel size / scale", which is not what you want -- you want the image to be of fixed size (36 x 36).

Use Auto Layout on circle:

override func viewDidLoad() {
    super.viewDidLoad()

    view.addSubview(memberIcons)
    memberIcons.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    memberIcons.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

    // Limit the stack view's width to no more than 75% of the superview's width
    // Adjust as needed
    memberIcons.widthAnchor.constraint(lessThanOrEqualTo: view.widthAnchor, multiplier: 0.75).isActive = true

    let width: CGFloat = 36.0
    for member in story!.members {
        // We don't care about the frame here as we're gonna use auto layout
        let circle = UIImageView(frame: .zero)
        circle.translatesAutoresizingMaskIntoConstraints = false
        circle.layer.cornerRadius = width / 2
        circle.image = member.profilePicture
        circle.contentMode = .scaleAspectFill
        circle.clipsToBounds = true
        circle.layer.borderWidth = 1
        circle.layer.borderColor = UIColor.lightGray.cgColor

        memberIcons.addArrangedSubview(circle)
        circle.widthAnchor.constraint(equalToConstant: width).isActive = true
        circle.heightAnchor.constraint(equalToConstant: width).isActive = true
    }
}

Result:

Apple's executives

Because we limit the width of the UIStackView, there a maximum number of profile images you can add (7 in this case) before you get a bunch of auto layout error on the console. You can enclose the Stack View inside a Scroll View or use a Collection View for a matrix-like display.

Code Different
  • 90,614
  • 16
  • 144
  • 163