Why is button background changing to blue when button selected? - ios

I have three buttons, when selected they change background color to red - yet a blue background is popping up as well and I can't figure out why (sorry if the reason is obvious, ive only been doing "programming" for 3 weeks. I can't find anything in the code that would explain itI have three buttons, when selected they change background color to red - yet a blue background is popping up as well and I can't figure out why (sorry if the reason is obvious, ive only been doing "programming" for 3 weeks. I can't find anything in the code that would explain it
[enter image description here][1]import UIKit
class ViewController: UIViewController {
var counterEN : Int = 0
var count = Array(1...150).filter { $0 % 1 != 0}.count
var pizzaCount = 0
#IBOutlet weak var pizzaCounter: UILabel!
#IBOutlet weak var textField: UITextField!
#IBAction func test(_ sender: UIButton) {
self.textField.text = sender.currentTitle
}
var lastY: CGFloat = 100
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func buttonClicked(_ sender: UIButton) {
pizzaCount = pizzaCount + 1
pizzaCounter.text = ("Antal pizza: ") + "\(pizzaCount)"
let contentView = UIView()
addViewsTo(contentView, title: sender.currentTitle)
contentView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(contentView)
// Add size constraints to the content view (260, 30)
NSLayoutConstraint(item: contentView, attribute: .width, relatedBy: .equal,
toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 850.0).isActive = true
NSLayoutConstraint(item: contentView, attribute: .height, relatedBy: .equal,
toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: ` 30.0).isActive = true
// Add position constraints to the content view (horizontal center, 100 from the top)
NSLayoutConstraint(item: contentView, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1.0, constant: lastY).isActive = true
NSLayoutConstraint(item: contentView, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 1.0, constant: 0.0).isActive = true
// Update last Y position to have the gaps between views to be 10
lastY += 50
}
// Add label and button to the content view
func addViewsTo(_ contentView: UIView, title: String?) {
// Add a label with size of (100, 30)
let label = UILabel()
label.text = title
//label.text = ("1 x 17 ")
label.frame = CGRect(x: 0.0, y: 0.0, width: 100.0, height: 30.0)
contentView.addSubview(label)
let DressingButton = UIButton(type: .system)
DressingButton.frame = CGRect(x: 210, y: 0, width: 40, height: 30)
DressingButton.setTitle("D", for: .normal)
DressingButton.setTitleColor(.black, for: .normal)
DressingButton.setTitleColor(.red, for: .selected)
DressingButton.sendActions(for: .touchUpInside)
contentView.addSubview(DressingButton)
DressingButton.addTarget(self, action: #selector(dressingAction(_:)), for .touchUpInside)
let Chili = UIButton(type: .system)
Chili.frame = CGRect(x: 160, y: 0, width: 40, height: 30)
Chili.setTitle("C", for: .normal)
Chili.setTitleColor(.black, for: .normal)
Chili.backgroundColor = UIColor.white
Chili.setTitleColor(.systemRed, for: .selected)
Chili.sendActions(for: .touchUpInside)
contentView.addSubview(Chili)
Chili.addTarget(self, action: #selector(dressingAction(_:)), for: .touchUpInside)
let Hvidløg = UIButton(type: .system)
Hvidløg.frame = CGRect(x: 110, y: 0, width: 40, height: 30)
Hvidløg.setTitle("H", for: .normal)
Hvidløg.setTitleColor(.black, for: .normal)
Hvidløg.setTitleColor(.red, for: .selected)
Hvidløg.backgroundColor = UIColor.white
Hvidløg.sendActions(for: .touchUpInside)
contentView.addSubview(Hvidløg)
Hvidløg.addTarget(self, action: #selector(dressingAction(_:)), for: .touchUpInside)
let button2 = UIButton(type: .system)
button2.frame = CGRect(x: -40, y: 20, width: 150, height: 30)
button2.setTitle("Alm", for: .normal)
button2.setTitle("Ful", for: .selected)
button2.setTitle("Glu", for: .selected)
// Set button action
button2.addTarget(self, action: #selector(buttonAction(_:)), for: .touchUpInside)
contentView.addSubview(button2)
self.view = view
}
#objc func dressingAction(_ sender:UIButton){
sender.isSelected.toggle()
print("knap")
sender.backgroundColor = UIColor.red
}
#objc func buttonAction(_ sender:UIButton!)
{
sender.isSelected = !sender.isSelected
sender.setTitle("Alm", for: .normal)
if sender.isSelected{
sender.setTitle("Fuld", for: .selected)}
else {
sender.setTitle("Glu", for: .selected)
sender.isSelected = !sender.isSelected
// sender.tintColor = .clear
//// if sender.isSelected{
// sender.setTitleColor(.green, for: .selected)
// }
// else{
// sender.setTitleColor(.blue, for: .selected)
//
func buttonAction(_ button3:UIButton!) {
print("Button tapped"); counterEN += 1; count += 1; print (counterEN); print (count)
}
}
}
}

Please change your button type to .custom and the issue will be solved.
let dressingButton = UIButton(type: .custom)

Try changing your button Type to custom

Related

Centering a view in another view and customising playground view size

I know questions like this have been posted on StackOverflow, but despite following the guides I haven't been able to manage my question.
I have a red rectangle that I would like to place in the center of a view, but it winds up at the origin, like so:
After following some guides, I have arrived at the following code, but the rectangle doesn't render at all.
//: A UIKit based Playground for presenting user interface
import UIKit
import PlaygroundSupport
import CoreGraphics
class MyViewController : UIViewController {
var currentDrawType = 0
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
// Buton logic follows
let button = UIButton(type: .system)
button.frame = CGRect(x:150, y:500, width:80, height:25)
button.backgroundColor = .white
button.setTitle("Test Button", for: .normal)
button.titleLabel?.textColor = .systemBlue
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
super.view.addSubview(button)
// Other
drawRectangle()
}
#objc func buttonAction(sender: UIButton!) {
currentDrawType += 1
if currentDrawType > 5 {
currentDrawType = 0
}
switch currentDrawType {
case 0:
drawRectangle()
default:
break
}
print(currentDrawType)
}
func drawRectangle() {
var imageView = UIImageView()
imageView.frame.origin = super.view.bounds.origin
imageView.frame.size = CGSize(width:200, height:200)
imageView.center = super.view.convert(super.view.center, from: imageView)
super.view.addSubview(imageView)
UIGraphicsBeginImageContextWithOptions(imageView.frame.size, false, 0)
let context = UIGraphicsGetCurrentContext()
let rectangle = imageView.frame
context!.setFillColor(UIColor.red.cgColor)
context!.setStrokeColor(UIColor.black.cgColor)
context!.setLineWidth(10)
context!.addRect(rectangle)
// Draw it now
context!.drawPath(using: CGPathDrawingMode.fillStroke)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
imageView.image = img
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
Furthermore, I would like to adjust the size of the main view, but I'm not quite sure how to. When I had a slightly different implementation, I did change the size, but the physical viewing window in Xcode where the result displayed did not change and hence elements were not visible.
I would love some help and/or guidance on this.
In func drawRectangle() you are setting origin with superview origin; which is by default x: 0 , y : 0.
imageView.frame.origin = super.view.bounds.origin // this make you view to top.
In order to fix this you need to get centre point of the view.
CGPoint.init(x: view.frame.size.width / 2 , y: view.frame.size.height / 2)
More i would suggest you to use Constraint here.
let xConstraint = NSLayoutConstraint(item: imageView, attribute: .CenterX, relatedBy: .Equal, toItem: self.view , attribute: .CenterX, multiplier: 1, constant: 0)
let yConstraint = NSLayoutConstraint(item: imageView, attribute: .CenterY, relatedBy: .Equal, toItem: self.view, attribute: .CenterY, multiplier: 1, constant: 0)
imageView.addConstraint(xConstraint)
imageView.addConstraint(yConstraint)
You have to make rectangle = imageView.bounds and have to calculate the frame of imageView using the code below
import UIKit
import CoreGraphics
class MyViewController : UIViewController {
var currentDrawType = 0
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
// Buton logic follows
let button = UIButton(type: .system)
button.frame = CGRect(x:150, y:500, width:80, height:25)
button.backgroundColor = .white
button.setTitle("Test Button", for: .normal)
button.titleLabel?.textColor = .systemBlue
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
super.view.addSubview(button)
// Other
drawRectangle()
}
#objc func buttonAction(sender: UIButton!) {
currentDrawType += 1
if currentDrawType > 5 {
currentDrawType = 0
}
switch currentDrawType {
case 0:
drawRectangle()
default:
break
}
print(currentDrawType)
}
func drawRectangle() {
let imageSize = CGSize(width:200, height:200)
var imageOrigin = self.view.center
imageOrigin.x -= imageSize.width/2
imageOrigin.y -= imageSize.height/2
let imageView = UIImageView(frame: CGRect(origin:imageOrigin , size: imageSize))
super.view.addSubview(imageView)
UIGraphicsBeginImageContextWithOptions(imageView.frame.size, false, 0)
let context = UIGraphicsGetCurrentContext()
let rectangle = imageView.bounds
context!.setFillColor(UIColor.red.cgColor)
context!.setStrokeColor(UIColor.black.cgColor)
context!.setLineWidth(10)
context!.addRect(rectangle)
// Draw it now
context!.drawPath(using: CGPathDrawingMode.fillStroke)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
imageView.image = img
}
}

UIStepper won't register any event

I'm adding a UIStepper to a horizontal UIStackView which itself is on a vertical UIStackView. The problem is that no matter what I do, the UIStepper won't register any event.
My code is the following
init(variableIndex: Int, variableName: String, withParentView parent: UIView, currentValue: String, readOnly: Bool) {
// Instantiate the properties
valueTextField = UITextField()
valueStepper = UIStepper()
numberOfDecimals = currentValue.components(separatedBy: ".").count > 1 ? currentValue.components(separatedBy: ".")[1].count : 1
numericValue = Double(currentValue)!
super.init(variableIndex: variableIndex, variableName: variableName, withParentView: parent)
// Horizontal Stack View
let horizontalStackView = UIStackView()
horizontalStackView.axis = .horizontal
horizontalStackView.alignment = .fill
horizontalStackView.spacing = 15
horizontalStackView.distribution = .fill
horizontalStackView.translatesAutoresizingMaskIntoConstraints = false
horizontalStackView.isUserInteractionEnabled = true
// Text Field
valueTextField.text = stringValue
valueTextField.textAlignment = .right
valueTextField.layer.borderWidth = 1.0
valueTextField.layer.cornerRadius = 6.0
valueTextField.layer.borderColor = UIColor.darkGray.cgColor
#warning ("TODO: Enable interaction, change keyboard to numeric and add done button to keyboard")
valueTextField.isUserInteractionEnabled = false
valueTextField.rightView = UIView(frame: CGRect(x: 0, y: 0, width: ConfigFile.rightPadding, height: Int(valueTextField.frame.size.height)))
valueTextField.rightViewMode = .always
// Stepper
valueStepper.value = numericValue
valueStepper.stepValue = 0.1
valueStepper.addTarget(self, action: #selector(self.stepperValueChanged(sender:)), for: .touchUpInside)
valueStepper.addTarget(self, action: #selector(self.test(sender:)), for: .allEditingEvents)
valueStepper.isEnabled = !readOnly
// Create the constraints
constraints.append(NSLayoutConstraint(item: horizontalStackView, attribute: .width, relatedBy: .equal, toItem: stackView, attribute: .width, multiplier: 1.0, constant: 0.0))
horizontalStackView.addArrangedSubview(valueTextField)
horizontalStackView.addArrangedSubview(valueStepper)
stackView.addArrangedSubview(horizontalStackView)
}
#objc private func stepperValueChanged(sender: UIStepper) {
numericValue = valueStepper.value
let userInfo = [
"VariableIndex": String(self.variableIndex),
"NewValue": self.stringValue
]
NotificationCenter.default.post(name: .numericVariableChanged, object: nil, userInfo: userInfo)
}
#objc private func test(sender: UIStepper) {
print("Hi")
}
As you can see, I add the events with the lines
valueStepper.addTarget(self, action: #selector(self.stepperValueChanged(sender:)), for: .touchUpInside)
valueStepper.addTarget(self, action: #selector(self.test(sender:)), for: .allEditingEvents)
I also tried using the .allTouchEvents argument on the second line but that didn't work.
All the views above the UIStepper have their isUserInteractionEnabled property set to true
During execution, I get feedback from the UIStepper when I press it (it changes color for a moment).
Use the .valueChanged event with a UIStepper, not .touchUpInside or .allEditingEvents.
I had the same issue as the one described in here
Problem was that I didn't hold any reference to the object I was generating so it was being deinitialized immediately. I solved this by keeping a reference to it in the ViewController that holds it.

Swift - Dynamic number of buttons in tableviewcell

Actually i have a project in github. The problem is that i cannot get why when scrolling, the buttons constraints in the cells are going crazy..
I didn't saw any project like this, then i have a reason to share it but i want to give a good example for another people.
I'll be very thankful with any help that drives me to the solution of this problem.
Best regards.
There it is the code for the cell:
import UIKit
class BookTableViewCell: UITableViewCell {
let nameLabel = UILabel()
let detailLabel = UILabel()
var cellButton = UIButton()
var cellLabel = UILabel()
var book : Book!
// MARK: Initalizers
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
func configureCellCon(botones:Int, titulo:String, book:Book) {
self.book = book
let marginGuide = contentView.layoutMarginsGuide
// configure titleLabel
contentView.addSubview(nameLabel)
nameLabel.translatesAutoresizingMaskIntoConstraints = false
nameLabel.leadingAnchor.constraint(equalTo: marginGuide.leadingAnchor).isActive = true
nameLabel.topAnchor.constraint(equalTo: marginGuide.topAnchor).isActive = true
nameLabel.trailingAnchor.constraint(equalTo: marginGuide.trailingAnchor).isActive = true
nameLabel.numberOfLines = 0
nameLabel.font = UIFont(name: "AvenirNext-DemiBold", size: 16)
nameLabel.text = book.name
// configure authorLabel
contentView.addSubview(detailLabel)
detailLabel.translatesAutoresizingMaskIntoConstraints = false
detailLabel.leadingAnchor.constraint(equalTo: marginGuide.leadingAnchor).isActive = true
// detailLabel.bottomAnchor.constraint(equalTo: marginGuide.bottomAnchor).isActive = true
detailLabel.trailingAnchor.constraint(equalTo: marginGuide.trailingAnchor).isActive = true
detailLabel.topAnchor.constraint(equalTo: nameLabel.bottomAnchor).isActive = true
detailLabel.numberOfLines = 0
detailLabel.font = UIFont(name: "Avenir-Book", size: 12)
detailLabel.textColor = UIColor.lightGray
detailLabel.text = book.details
var lastButton = UIButton()
if(book.buttonsAttibutes.count == 1) {
let button = UIButton()
button.tag = 0
button.backgroundColor = UIColor.init(white: 0.9, alpha: 0.0)
// button.setBackgroundColor(color: UIColor.white, forState: .normal)
// button.setBackgroundColor(color: UIColor.blue, forState: .normal)
button.setTitle(book.buttonsAttibutes[0].title, for: .normal)
button.setTitleColor(UIColor.blue.withAlphaComponent(0.7), for: .normal)
button.setTitleColor(UIColor.init(white: 0.8, alpha: 1), for: .highlighted)
button.layer.borderWidth = 0
button.layer.borderColor = UIColor.blue.cgColor
contentView.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
contentView.addConstraints([
NSLayoutConstraint(item: button, attribute: .leftMargin, relatedBy: .equal, toItem: contentView, attribute: .leftMargin, multiplier: 1.0, constant: 20),
NSLayoutConstraint(item: button, attribute: .rightMargin, relatedBy: .equal, toItem: contentView, attribute: .rightMargin, multiplier: 1.0, constant: -20),
])
button.topAnchor.constraint(equalTo: detailLabel.bottomAnchor).isActive = true
button.bottomAnchor.constraint(equalTo: marginGuide.bottomAnchor).isActive = true
button.addTarget(self, action:#selector(mostrarMensaje), for:.touchUpInside)
return
}else if(book.buttonsAttibutes.count == 0) {
detailLabel.bottomAnchor.constraint(equalTo: marginGuide.bottomAnchor).isActive = true
return
}
if(book.buttonsAttibutes.count > 0) {
for x in 0...(book.buttonsAttibutes.count - 1) {
let button = UIButton()
button.tag = x
button.backgroundColor = UIColor.init(white: 0.9, alpha: 0.0)
// button.setBackgroundColor(color: UIColor.white, forState: .normal)
// button.setBackgroundColor(color: UIColor.blue, forState: .normal)
button.setTitle(book.buttonsAttibutes[x].title, for: .normal)
button.setTitleColor(UIColor.blue.withAlphaComponent(0.7), for: .normal)
button.setTitleColor(UIColor.init(white: 0.8, alpha: 1), for: .highlighted)
button.layer.borderWidth = 0
button.layer.borderColor = UIColor.blue.cgColor
contentView.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
// button.leadingAnchor.constraint(equalTo: marginGuide.leadingAnchor).isActive = true
// button.trailingAnchor.constraint(equalTo: marginGuide.trailingAnchor).isActive = true
contentView.addConstraints([
NSLayoutConstraint(item: button, attribute: .leftMargin, relatedBy: .equal, toItem: contentView, attribute: .leftMargin, multiplier: 1.0, constant: 20),
NSLayoutConstraint(item: button, attribute: .rightMargin, relatedBy: .equal, toItem: contentView, attribute: .rightMargin, multiplier: 1.0, constant: -20),
])
if(x == 0){
if #available(iOS 11.0, *) {
button.layer.cornerRadius = 8
button.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
} else {
button.layer.cornerRadius = 5
}
button.topAnchor.constraint(equalTo: detailLabel.bottomAnchor).isActive = true
}else if(x == (book.buttonsAttibutes.count - 1)){
if #available(iOS 11.0, *) {
button.layer.cornerRadius = 8
button.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
} else {
button.layer.cornerRadius = 5
}
button.topAnchor.constraint(equalTo: lastButton.bottomAnchor).isActive = true
button.bottomAnchor.constraint(equalTo: marginGuide.bottomAnchor).isActive = true
}else{
button.topAnchor.constraint(equalTo: lastButton.bottomAnchor).isActive = true
}
button.addTarget(self, action:#selector(mostrarMensaje), for:.touchUpInside)
lastButton = button
}
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
#objc func mostrarMensaje(sender: UIButton){
let message = self.book.buttonsAttibutes[sender.tag].message
let alertController = UIAlertController(title: "\(self.book.name)", message: message, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "Cerrar", style: UIAlertActionStyle.default) {
(result : UIAlertAction) -> Void in
}
alertController.addAction(okAction)
if let myViewController = parentViewController {
print(myViewController.title ?? "ViewController without title.")
myViewController.present(alertController, animated: true, completion: nil)
}
}
}
Ok, i went for the "InterfaceBuilder" and did it properly.
However, I'll be reading more about programmatic methods to do it.
thanks to all of you for the guide.
When creating the buttons and constraints programmatically, they are generating more constraints over the same cells making them crash.

How to arrange 3 UIButtons side-by-side in swift3 programmatically

I want to arrange 3 UIButtons side-by-side in swift3 programmatically,
they should be equal width regardless of device. please be details code with constraints .
here I have tried with constraint , all buttons are in centre together. this is my code,
let addToWishListBtn: UIButton = {
let btn = UIButton()
btn.setTitle("Add to Wish List", for: UIControlState())
btn.setImage(UIImage(named: "service_icon"), for: UIControlState())
btn.setTitleColor(.black, for: UIControlState())
btn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 10)
btn.addTarget(self, action: #selector(addToWishListBtnTarget), for: .touchUpInside)
btn.imageEdgeInsets = UIEdgeInsetsMake(20, 50, 40, 0)
btn.titleEdgeInsets = UIEdgeInsetsMake(20, 0, 0, 0)
btn.backgroundColor = .yellow
btn.translatesAutoresizingMaskIntoConstraints = false
return btn
}()
func addToWishListBtnTarget() {
print("add to wish btn target")
}
let emailToFriendBtn: UIButton = {
let btn = UIButton()
btn.setTitle("Email to Friend", for: .normal)
btn.setImage(UIImage(named:"service_icon"), for: .normal)
btn.setTitleColor(.black, for: .normal)
btn.titleLabel?.textAlignment = .center
btn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 10)
btn.addTarget(self, action: #selector(emailToFriendBtnTarget), for: .touchUpInside)
btn.imageEdgeInsets = UIEdgeInsetsMake(20, 50, 40, 0)
btn.titleEdgeInsets = UIEdgeInsetsMake(20, 0, 0, 0)
btn.translatesAutoresizingMaskIntoConstraints = false
return btn
}()
func emailToFriendBtnTarget() {
print(" email to friend target")
}
let shareBtn: UIButton = {
let btn = UIButton()
btn.setTitle("Share", for: UIControlState())
btn.setImage(UIImage(named: "service_icon"), for: .normal)
btn.setTitleColor(.black, for: UIControlState())
btn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 10)
btn.addTarget(self, action: #selector(shareBtnTarget), for: .touchUpInside)
btn.imageEdgeInsets = UIEdgeInsetsMake(20, 50, 40, 0)
btn.titleEdgeInsets = UIEdgeInsetsMake(20, 0, 0, 0)
btn.translatesAutoresizingMaskIntoConstraints = false
btn.backgroundColor = .purple
// button.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
btn.backgroundColor = .green
return btn
}()
func shareBtnTarget() {
print("share btn target")
}
view.addSubview(addToWishListBtn)``
view.addSubview(emailToFriendBtn)
view.addSubview(shareBtn)
addToWishListBtn.topAnchor.constraint(equalTo: view.topAnchor, constant: 380).isActive = true
addToWishListBtn.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
addToWishListBtn.widthAnchor.constraint(equalToConstant: 125).isActive = true
addToWishListBtn.heightAnchor.constraint(equalToConstant: 50).isActive = true
emailToFriendBtn.topAnchor.constraint(equalTo: view.topAnchor, constant: 380).isActive = true
// addToWishListBtn.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
emailToFriendBtn.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
emailToFriendBtn.widthAnchor.constraint(equalToConstant: 125).isActive = true
emailToFriendBtn.heightAnchor.constraint(equalToConstant: 50).isActive = true
addToWishListBtn.topAnchor.constraint(equalTo: view.topAnchor, constant: 380).isActive = true
addToWishListBtn.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
addToWishListBtn.widthAnchor.constraint(equalToConstant: 125).isActive = true
addToWishListBtn.heightAnchor.constraint(equalToConstant: 50).isActive = true
You need to give following constraints..
btn1 leading to its superview
btn2 leading to btn1 trailing
btn3 leading to btn2 trailing
btn3 trailing to its superview
btn1 equal width to btn2
btn2 equal width to btn3
btn1 top to its superview
btn2 top to its superview
btn3 top to its superview
for all 3 buttons you also need to give height constraints.
You can give constraints by constraintsWithVisualFormat or constraintWithItem.
EDIT:
Take a look...
//all 3 buttons will be in views dict.
let views = ["btn1" : btn1, "btn2" : btn2, "btn3": btn3];
// align btn1 from the top
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-8-[btn1]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views));
// align btn2 from the top
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-8-[btn2]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views));
// align btn3 from the top
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-8-[btn3]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views));
//horizontal constraints
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-8-[btn1]-8-[btn2]-8-[btn3]-8-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views));
// height constraint if you want to give
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[btn1(==30)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views));
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[btn2(==30)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views));
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[btn3(==30)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views));
//equal width for all 3 btns
self.view.addConstraint(NSLayoutConstraint.init(item: btn1, attribute: .width, relatedBy: .equal, toItem: btn2, attribute: .width, multiplier: 1.0, constant: 0))
self.view.addConstraint(NSLayoutConstraint.init(item: btn2, attribute: .width, relatedBy: .equal, toItem: btn3, attribute: .width, multiplier: 1.0, constant: 0))
You have two options
1) create constraints (Little long and harder)
2) Use Stack View
If your app runs ios9+ You can use UIStackView
so create UIStackView programatically
and add 3 buttons to it it will automatically adjust width accordingly
Here is an example
let labelOne = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 21))
labelOne.text = "Hello"
labelOne.backgroundColor = UIColor.red
let labelTwo = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 21))
labelTwo.text = "There"
labelTwo.backgroundColor = UIColor.blue
let myStack = UIStackView(arrangedSubviews: [labelOne, labelTwo])
myStack.distribution = .fillEqually
myStack.axis = .horizontal
Enjoy ...
Hope it helps to you

Custom View size in iOS not dynamic

I just have started my first app on iOS a week ago. I have created a custom view to use it in my app using AppleDeveloperWebsite Custom Rating Control Tutorial.
Now I have chosen iPhone7 device in storyboard and I run this on iPhone 7 emulator it works perfectly but when I run it on iPhone 5 emulator (size of screen changes) my custom views extend beyond the screen. My all other controls sizes resize as I set constraints but only my custom view sizes get messed up.
Please Help
import UIKit
#IBDesignable class xRadioButtonView: UIView {
var button: UIButton!
var label: UILabel!
#IBInspectable var text: String? {
didSet{
label.text = text
}
}
//Properties
var isSelected = 0
//Initialization
override init(frame: CGRect){
super.init(frame: frame)
addSubviews()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
addSubviews()
}
func addSubviews() {
self.backgroundColor = UIColor.white
let xWidth = bounds.size.width
let xHeight = bounds.size.height
let tap = UITapGestureRecognizer(target: self, action: #selector(xRadioButtonView.radioButtonTextTapped))
button = UIButton(frame: CGRect(x: 1, y: 1, width: xWidth - 2, height: xHeight - 4))
button.backgroundColor = UIColor.white
button.addTarget(self, action: #selector(xRadioButtonView.radioButtonTapped(button:)), for: .touchDown)
addSubview(button)
label = UILabel(frame: CGRect(x: 1, y: 1, width: xWidth - 2, height: xHeight - 2))
label.textColor = UIColor.init(hex: "#D5D5D5")
//label.font = UIFont.init(name: label.font.fontName, size: 25)
//label.font = label.font.withSize(25)
label.font = UIFont.boldSystemFont(ofSize: 25)
label.textAlignment = NSTextAlignment.center
label.isUserInteractionEnabled = true
label.addGestureRecognizer(tap)
addSubview(label)
}
override func layoutSubviews() {
// Set the button's width and height to a square the size of the frame's height.
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
label.text = "xRBV"
}
func radioButtonTapped(button: UIButton) {
if isSelected == 0 {
isSelected = 1
self.backgroundColor = UIColor.init(hex: "#00BFA5")
label.textColor = UIColor.init(hex: "#00BFA5")
} else {
isSelected = 0
self.backgroundColor = UIColor.white
label.textColor = UIColor.init(hex: "#D5D5D5")
}
}
func radioButtonTextTapped(sender: UITapGestureRecognizer){
if isSelected == 0 {
isSelected = 1
self.backgroundColor = UIColor.init(hex: "#00BFA5")
label.textColor = UIColor.init(hex: "#00BFA5")
} else {
isSelected = 0
self.backgroundColor = UIColor.white
label.textColor = UIColor.init(hex: "#D5D5D5")
}
}
}
As you can see PG button should finish where green color finishes but white color button is extended beyond the screen
You either need to set the frame in layoutSubViews or you need to implement autolayout in code:
button = UIButton(frame: CGRect(x: 1, y: 1, width: xWidth - 2, height: xHeight - 4))
button.backgroundColor = UIColor.white
button.addTarget(self, action: #selector(xRadioButtonView.radioButtonTapped(button:)), for: .touchDown)
addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
let attributes: [NSLayoutAttribute] = [.top, .bottom, .leading, .trailing]
let constants = [2, 2, 10, 10] // 2 from top and bottom, 10 from leading and trailing
NSLayoutConstraint.activate(attributes.enumerated().map { NSLayoutConstraint(item: button, attribute: $1, relatedBy: .equal, toItem: button.superview, attribute: $1, multiplier: 1, constant: constants[$0]) })
The example uses the old way because your constraints are uniform, but if you have something more complicated its often simpler to use NSLayoutAnchor as of iOS 9.
EDIT: here is the code for tuples if anyone is interested:
button.translatesAutoresizingMaskIntoConstraints = false
let attributes: [(NSLayoutAttribute, CGFloat)] = [(.top, 2), (.bottom, 2), (.leading, 12), (.trailing, 12)]
NSLayoutConstraint.activate(attributes.map { NSLayoutConstraint(item: button, attribute: $0.0, relatedBy: .equal, toItem: button.superview, attribute: $0.0, multiplier: 1, constant: $0.1) })
Thanks I wasn't even aware of this NSLayout yet. (HEHE 7 Days) Thanks to you I have a solution for my problem. Although I wanted different values for .top .bottom .leading .trailling
I used your code like this
NSLayoutConstraint(item: button, attribute: .top, relatedBy: .equal, toItem: button.superview, attribute: .top, multiplier: 1, constant: 1).isActive = true
NSLayoutConstraint(item: button, attribute: .bottom, relatedBy: .equal, toItem: button.superview, attribute: .bottom, multiplier: 1, constant: 4).isActive = true
to all 4 sides. But is there a way to provide constant values as well like you have provided multiple attribute values?

Resources