Craig Jarman Craig Jarman - 9 months ago 30
Swift Question

How to apply rounded corners for button programaticlly added to a StackView

I'm having an issue with adding top right and left rounded button, to a stackview. Buttons added via interface builder, and then rounded by the extension, will render, but not if the button is added via code. Posisbly there is some addtional attribute that IB applies.

Here is an extract of the code, which illustrates the problem.

import UIKit

class TestViewController: UIViewController {
let colorDictionary = ["Red":UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0),"Green":UIColor(red: 0.0, green: 1.0, blue: 0.0, alpha: 1.0),"Blue":UIColor(red: 0.0, green: 0.0, blue: 1.0, alpha: 1.0),]

func colorButton(withColor color:UIColor, title:String) -> UIButton{
let newButton = UIButton(type: .system)
newButton.backgroundColor = color
newButton.setTitle(title, for: .normal)
newButton.setTitleColor(UIColor.white, for: .normal)

//Buttons fail to render if roundedButton() is applied
//**************************
//newButton.roundedButton()
//**************************
return newButton
}


override func viewDidLoad() {
super.viewDidLoad()
displayButtonsInStackView()
}

func displayButtonsInStackView(){
//generate an array

var buttonArray = [UIButton]()
for (myKey,myValue) in colorDictionary{
buttonArray += [colorButton(withColor: myValue, title: myKey)]
}

let stackView = UIStackView(arrangedSubviews: buttonArray)
stackView.axis = .horizontal
stackView.distribution = .fillEqually
stackView.alignment = .fill
stackView.spacing = 5
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView)

//autolayout the stack view - pin 30 up 20 left 20 right 30 down
let viewsDictionary = ["stackView":stackView]
let stackView_H = NSLayoutConstraint.constraints(withVisualFormat: "H:|-20-[stackView]-20-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewsDictionary)
let stackView_V = NSLayoutConstraint.constraints(withVisualFormat: "V:|-30-[stackView]-30-|", options: NSLayoutFormatOptions(rawValue:0), metrics: nil, views: viewsDictionary)
view.addConstraints(stackView_H)
view.addConstraints(stackView_V)
}
}

extension UIButton {

func roundedButton(){
let maskPath = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: [.bottomRight , .topRight],
cornerRadii:CGSize(width:8.0, height:8.0))
let maskLayer = CAShapeLayer()
maskLayer.frame = self.bounds
maskLayer.path = maskPath.cgPath
self.layer.mask = maskLayer
}
}

Answer Source

The problem is that your buttons have no size. Change this:

// ...
newButton.setTitleColor(UIColor.white, for: .normal)
newButton.roundedButton()
// ...

to this:

// ...
newButton.setTitleColor(UIColor.white, for: .normal)
newButton.sizeToFit()
newButton.roundedButton()
// ...