swiftuistackviewrounded-cornersios12

UIStackView rounded corners for deployment target 12.3


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:

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?


Solution

  • 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