1

I can easily create a stackview with rounded corners in iOS 14 by doing:

    stackView.layer.cornerRadius = 10
    stackView.clipsToBounds = true

without doing anything else. But since I want my app to also work on iPhone 6 that can't go beyond iOS 12, the above 2 lines of code don't do anything. I have looked at How can I set the cornerRadius of a UIStackView? and adapted the code to my app, but it still doesn't work. To be clear, I have:

  • Changed my build settings to use a deployment target of iOS 12.3
  • Excluded references to scenes and added window variable (Add iOS 12 support to a new Xcode 11 Project)
  • Tested with iPhone 11 and iphone 6 simulator (both did not show rounded corners)

Here's my code:

import UIKit

class ViewController: UIViewController {
    
    let buttonList = ["Dog", "Cat", "Mouse"]

    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .black
        
        let stackView = UIStackView()
        stackView.axis = .vertical
        stackView.distribution = .fillEqually
        stackView.alignment = .fill
        stackView.spacing = 6
        stackView.backgroundColor = .systemPink // this actually works
        view.addSubview(stackView)
        
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        stackView.widthAnchor.constraint(equalToConstant: 140).isActive = true
        
        // The following is "supposed" to create rounded corners for the stackview
        let subView = UIView(frame: stackView.bounds)
        subView.backgroundColor = .yellow // this ends up showing through instead of the systemPink
        subView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        stackView.insertSubview(subView, at: 0)
        subView.layer.cornerRadius = 10
        subView.layer.masksToBounds = true
        subView.clipsToBounds = true
        
        // Fill the stackview with buttons
        for index in 0..<buttonList.count {
            let button = UIButton()
            button.setTitle(buttonList[index], for: .normal)
            button.backgroundColor = .cyan
            button.setTitleColor(.black, for: .normal)
            button.titleLabel?.font = UIFont.systemFont(ofSize: 14)
            stackView.addArrangedSubview(button)
        }
    }
}

And this is what it looks like (no rounded corners):

Stackview doesn't have rounded corners

So what am I missing? How can I make my stackview appear to have rounded corners for iPhone 6 (iOS 12) and above?

Kaplan
  • 91
  • 1
  • 11

1 Answers1

2

You could place your stackView inside another view and set background color/corner radius for this container view:

override func viewDidLoad() {
    super.viewDidLoad()
    
    view.backgroundColor = .black
           
    // The following is "supposed" to create rounded corners for the stackview
    let subView = UIView()
    subView.backgroundColor = .yellow // this ends up showing through instead of the systemPink
    subView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    subView.layer.cornerRadius = 10
    subView.layer.masksToBounds = true
    subView.clipsToBounds = true
    view.addSubview(subView)
    subView.translatesAutoresizingMaskIntoConstraints = false
                            
    let stackView = UIStackView()
    stackView.axis = .vertical
    stackView.distribution = .fillEqually
    stackView.alignment = .fill
    stackView.spacing = 6
    stackView.backgroundColor = .systemPink // this actually works
    
    subView.addSubview(stackView)
    stackView.translatesAutoresizingMaskIntoConstraints = false
    
    // Fill the stackview with buttons
    for index in 0..<buttonList.count {
        let button = UIButton()
        button.setTitle(buttonList[index], for: .normal)
        button.backgroundColor = .cyan
        button.setTitleColor(.black, for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 14)
        stackView.addArrangedSubview(button)
    }
    
    NSLayoutConstraint.activate([
        stackView.trailingAnchor.constraint(equalTo: subView.trailingAnchor),
        stackView.leadingAnchor.constraint(equalTo: subView.leadingAnchor),
        stackView.topAnchor.constraint(equalTo: subView.topAnchor),
        stackView.bottomAnchor.constraint(equalTo: subView.bottomAnchor),
        
        subView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        subView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        subView.widthAnchor.constraint(equalToConstant: 140)
    ])
}

As far as I know, it is also better to activate NSLayoutConstraint in a group, not one by one

enter image description here

Viktor Gavrilov
  • 830
  • 1
  • 8
  • 13
  • Wow, so it's pretty much a matter of switching the UIStackView and the extra "helper" UIView around? Yes, this works. Thank you. The only inconsistent thing I noticed is that the systemPink background color shows through on an iPhone 11 simulator, but the yellow background color shows through on an iPhone 6 simulator. – Kaplan Aug 21 '21 at 08:00
  • 1
    On iPhone 6 you can't set background color for stackView (pink), thus you see background color for the container view (yellow). As you wrote in the question, it is related to iOS 14 updates. There is a detailed article about these changes: https://useyourloaf.com/blog/stack-view-background-color-in-ios-14/ – Viktor Gavrilov Aug 21 '21 at 08:14