Related
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
I have a header view with a label and a button. I'm adding the constraints like this:
//create a view, button and label
view.addSubview(label)
view.addSubview(button)
label.translatesAutoresizingMaskIntoConstraints = false
button.translatesAutoresizingMaskIntoConstraints = false
let views = ["label": label, "button": button, "view": view]
let horizontallayoutContraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-19-[label]-60-[button]-22-|", options: .alignAllCenterY, metrics: nil, views: views)
view.addConstraints(horizontallayoutContraints)
let verticalLayoutContraint = NSLayoutConstraint(item: label, attribute: .centerY, relatedBy: .equal, toItem: view, attribute: .centerY, multiplier: 1, constant: 0)
view.addConstraint(verticalLayoutContraint)
return view
This works really well but now I'd like to add a divider view that spans the width above the label and button. Something like this:
let frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: 10)
let divView = UIView(frame: frame)
divView.backgroundColor = UIColor.lightGray
I can't seem to figure out the combination of constraints to make this happen. Basically I want the divView to span the width of the tableview and the existing views to sit below it. Ideally I could nest it like this:
V:|[divView]-20-[H:|-19-[label]-60-[button]-22-|]-20-|
Any experts out there that can help me figure this out? I could just make a NIB but I'd prefer to do it programmatically.
Granted, I have done very, very little with Visual Format Language, but as far as I know you cannot nest in that manner.
Depending on exactly what you are trying to get as an end result, and what else might get added to this view (labels? images? etc), you might find it easier to use a UIStackView or two.
However, here is an example of using VFL... this will run as-is in a Playground, so it will be easy to make adjustments to see the effect. Also note that I did it two ways - align the label and button to the divider, or align the divider to the label and button. The comments and the if block should be pretty self-explanatory. The colors are just to make it easy to see where the elements' frames end up.
import UIKit
import PlaygroundSupport
let container = UIView(frame: CGRect(x: 0, y: 0, width: 600, height: 600))
container.backgroundColor = UIColor.green
PlaygroundPage.current.liveView = container
// at this point, we have a 600 x 600 green square to use as a playground "canvas"
// create a 400x100 view at x: 40 , y: 40 as a "header view"
let headerView = UIView(frame: CGRect(x: 40, y: 40, width: 400, height: 100))
headerView.backgroundColor = UIColor.blue
// add the Header View to our "main container view"
container.addSubview(headerView)
var label: UILabel = {
let l = UILabel()
l.backgroundColor = UIColor.yellow
l.text = "The Label"
return l
}()
var button: UIButton = {
let l = UIButton()
l.backgroundColor = UIColor.red
l.setTitle("The Button", for: .normal)
return l
}()
var divView: UIView = {
let v = UIView()
v.backgroundColor = UIColor.lightGray
return v
}()
headerView.addSubview(divView)
headerView.addSubview(label)
headerView.addSubview(button)
divView.translatesAutoresizingMaskIntoConstraints = false
label.translatesAutoresizingMaskIntoConstraints = false
button.translatesAutoresizingMaskIntoConstraints = false
var vcs: [NSLayoutConstraint]
var views = ["divView": divView, "label": label, "button": button, "headerView": headerView]
let bAlignToDivider = true
if bAlignToDivider {
// use the width of the divView to control the left/right edges of the label and button
// V: pin divView to the top, with a height of 10
vcs = NSLayoutConstraint.constraints(withVisualFormat:
"V:|[divView(10)]", options: [], metrics: nil, views: views)
headerView.addConstraints(vcs)
// H: pin divView 20 from the left, and 20 from the right
vcs = NSLayoutConstraint.constraints(withVisualFormat:
"H:|-20-[divView]-20-|", options: [], metrics: nil, views: views)
headerView.addConstraints(vcs)
// V: pin label to bottom of divView (plus spacing of 8)
// using .alignAllLeft will pin the label's left to the divView's left
vcs = NSLayoutConstraint.constraints(withVisualFormat:
"V:[divView]-8-[label]", options: .alignAllLeft, metrics: nil, views: views)
headerView.addConstraints(vcs)
// V: pin button to bottom of divView (plus spacing of 8)
// using .alignAllRight will pin the button's right to the divView's right
vcs = NSLayoutConstraint.constraints(withVisualFormat:
"V:[divView]-8-[button]", options: .alignAllRight, metrics: nil, views: views)
headerView.addConstraints(vcs)
// H: add ">=0" spacing between label and button, so they use intrinsic widths
vcs = NSLayoutConstraint.constraints(withVisualFormat:
"H:[label]-(>=0)-[button]", options: .alignAllCenterY, metrics: nil, views: views)
headerView.addConstraints(vcs)
}
else
{
// use left/right edges of the label and button to control the width of the divView
// H: pin label 20 from left
// pin button 20 from right
// use ">=0" spacing between label and button, so they use intrinsic widths
// also use .alignAllCenterY to vertically align them
vcs = NSLayoutConstraint.constraints(withVisualFormat:
"H:|-20-[label]-(>=0)-[button]-20-|", options: .alignAllCenterY, metrics: nil, views: views)
headerView.addConstraints(vcs)
// V: pin divView to the top, with a height of 10
vcs = NSLayoutConstraint.constraints(withVisualFormat:
"V:|[divView(10)]", options: [], metrics: nil, views: views)
headerView.addConstraints(vcs)
// V: pin label to bottom of divView (plus spacing of 8)
// using .alignAllLeft will pin the divView's left to the label's left
vcs = NSLayoutConstraint.constraints(withVisualFormat:
"V:[divView]-8-[label]", options: .alignAllLeft, metrics: nil, views: views)
headerView.addConstraints(vcs)
// V: pin button to bottom of divView (plus spacing of 8)
// using .alignAllRight will pin the divView's right to the button's right
vcs = NSLayoutConstraint.constraints(withVisualFormat:
"V:[divView]-8-[button]", options: .alignAllRight, metrics: nil, views: views)
headerView.addConstraints(vcs)
}
Edit: Here is another variation.
This time, the "header view" will have only the x,y position set... Its width and height will be auto-determined by its content.
The gray "div" view's position and width will be controlled by constraining it to the label and button, which will use your specified values:
"H:|-19-[label]-60-[button]-22-|"
Again, you can just copy/paste this into a playground page...
import UIKit
import PlaygroundSupport
let container = UIView(frame: CGRect(x: 0, y: 0, width: 600, height: 600))
container.backgroundColor = UIColor.green
PlaygroundPage.current.liveView = container
// at this point, we have a 600 x 600 green square to use as a playground "canvas"
var label: UILabel = {
let l = UILabel()
l.backgroundColor = UIColor.yellow
l.text = "This is a longer Label"
return l
}()
var button: UIButton = {
let l = UIButton()
l.backgroundColor = UIColor.red
l.setTitle("The Button", for: .normal)
return l
}()
var divView: UIView = {
let v = UIView()
v.backgroundColor = UIColor.lightGray
return v
}()
var headerView: UIView = {
let v = UIView()
v.backgroundColor = UIColor.blue
return v
}()
// add our header view
container.addSubview(headerView)
// add div, label and button as subviews in headerView
headerView.addSubview(divView)
headerView.addSubview(label)
headerView.addSubview(button)
// disable Autoresizing Masks
headerView.translatesAutoresizingMaskIntoConstraints = false
divView.translatesAutoresizingMaskIntoConstraints = false
label.translatesAutoresizingMaskIntoConstraints = false
button.translatesAutoresizingMaskIntoConstraints = false
var vcs: [NSLayoutConstraint]
var views = ["divView": divView, "label": label, "button": button, "headerView": headerView]
// init "header view" - we'll let its contents determine its width and height
// these two formats will simply put the header view at 20,20
vcs = NSLayoutConstraint.constraints(withVisualFormat:
"H:|-20-[headerView]", options: [], metrics: nil, views: views)
container.addConstraints(vcs)
vcs = NSLayoutConstraint.constraints(withVisualFormat:
"V:|-20-[headerView]", options: [], metrics: nil, views: views)
container.addConstraints(vcs)
// H: pin label 19 from left
// pin button 22 from right
// use 60 spacing between label and button
// width of label and button auto-determined by text
// also use .alignAllCenterY to vertically align them
vcs = NSLayoutConstraint.constraints(withVisualFormat:
"H:|-19-[label]-60-[button]-22-|", options: .alignAllCenterY, metrics: nil, views: views)
headerView.addConstraints(vcs)
// V: pin divView to the top, with a height of 10
vcs = NSLayoutConstraint.constraints(withVisualFormat:
"V:|[divView(10)]", options: [], metrics: nil, views: views)
headerView.addConstraints(vcs)
// V: pin label to bottom of divView (plus spacing of 20)
// using .alignAllLeft will pin the divView's left to the label's left
vcs = NSLayoutConstraint.constraints(withVisualFormat:
"V:[divView]-20-[label]", options: .alignAllLeft, metrics: nil, views: views)
headerView.addConstraints(vcs)
// V: pin button to bottom of divView (plus spacing of 20)
// using .alignAllRight will pin the divView's right to the button's right
vcs = NSLayoutConstraint.constraints(withVisualFormat:
"V:[divView]-20-[button]|", options: .alignAllRight, metrics: nil, views: views)
headerView.addConstraints(vcs)
I'm new to Swift and I try to make my first iOS app.
I have a problem with UILabels.
Made one which is centered (x and y) - its in the middle of the frame which is perfect.
//UILabel1 (works)
Level = UILabel(frame: CGRect(x: 0, y: 0, width: 150, height: 100))
Level.center = (self.view?.center)!
Level.textAlignment = NSTextAlignment.Center
Now I have 2 more, which I want in the center of x, but y should be higher so that they are higher on the screen.
I can center them like Level .. That works, but if I try to change "y" (in CGRect()) or if I delete the .center (self.view?.center)! it just disappears of the screen.
GeschwindigkeitUILabel = UILabel(frame: CGRect(x: 0, y: 0, width: 300, height: 50))
GeschwindigkeitUILabel.center = (self.view?.center)!
Regel = UILabel(frame: CGRect(x: 0, y: 0, width: 300, height: 50))
Regel.center = (self.view?.center)!
How can I make GeschwindigkeitUILabel and Regel in the center of x but with a higher y value?
Tried self.view.height / 2 + 150 and things like that too, but then I can't see the label at all.
Updated Answer:
Instead of calculating frames, you can do it pretty easily using Auto layouts.
I have done demo project for your scenario, and below is the View it looks like (I have turned on the ShowViewFrame):
Here are the constraints i have used to make this:
let topLabel = UILabel()
topLabel.translatesAutoresizingMaskIntoConstraints = false
topLabel.text = "TopLabel"
topLabel.textAlignment = NSTextAlignment.Center
let middleLabel = UILabel()
middleLabel.translatesAutoresizingMaskIntoConstraints = false
middleLabel.text = "MiddleLabel"
middleLabel.textAlignment = NSTextAlignment.Center
let bottomtLabel = UILabel()
bottomtLabel.translatesAutoresizingMaskIntoConstraints = false
bottomtLabel.text = "BottomLabel"
bottomtLabel.textAlignment = NSTextAlignment.Center
self.view.addSubview(topLabel)
self.view.addSubview(middleLabel)
self.view.addSubview(bottomtLabel)
//Ideally we should create dictionary for metrics and view to increase the code readability.
//Metrics are used specify width, height, spacing between views.
let metrics = ["spacingBetweenMiddleLabelAndTopLabel" : 25, "spacingBetweenMiddleLabelAndBottomLabel": 25]
//Views we provide the subview for which we are setting the constraints
let views = ["topLabel": topLabel, "middleLabel": middleLabel, "bottomtLabel": bottomtLabel]
//Placing middleLabel at the centre of screen Horizontal
let centreXMiddleLabel:NSLayoutConstraint = NSLayoutConstraint(item: middleLabel, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0);
//Placing middleLabel at the centre of screen Vertical
let centreVMiddleLabel:NSLayoutConstraint = NSLayoutConstraint(item: middleLabel, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0);
//Placing topLabel at the centre of screen Horizontal
let centreXTopLabel:NSLayoutConstraint = NSLayoutConstraint(item: topLabel, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0);
//Placing bottomtLabel at the centre of screen Horizontal
let centreXBottomtLabel:NSLayoutConstraint = NSLayoutConstraint(item: bottomtLabel, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0);
//Setting height of 50pts to topLable
let heightTopLabel = NSLayoutConstraint.constraintsWithVisualFormat("V:[topLabel(50)]", options: [], metrics: nil, views: views)
//Setting width of 300pts to topLable
let widthTopLabel = NSLayoutConstraint.constraintsWithVisualFormat("H:[topLabel(300)]", options: [], metrics: nil, views: views)
//Setting height of 100pts to middleLabel
let heightMiddleLabel = NSLayoutConstraint.constraintsWithVisualFormat("V:[middleLabel(100)]", options: [], metrics: nil, views: views)
//Setting width of 150pts to middleLabel
let widthMiddleLabel = NSLayoutConstraint.constraintsWithVisualFormat("H:[middleLabel(150)]", options: [], metrics: nil, views: views)
//Setting height of 50pts to bottomtLabel
let heightBottomLabel = NSLayoutConstraint.constraintsWithVisualFormat("V:[bottomtLabel(50)]", options: [], metrics: nil, views: views)
//Setting width of 300pts to bottomtLabel
let widthBottomLabel = NSLayoutConstraint.constraintsWithVisualFormat("H:[bottomtLabel(300)]", options: [], metrics: nil, views: views)
/*This is important
Here you are setting the Y position of all lables
We are placing top label on top of middleLabel with standand spacing (8 pts) and bottom label below middle label with standard spacing.
*/
let labelYConstraint = NSLayoutConstraint.constraintsWithVisualFormat("V:[topLabel]-(spacingBetweenMiddleLabelAndTopLabel)-[middleLabel]-(spacingBetweenMiddleLabelAndBottomLabel)-[bottomtLabel]", options: [], metrics: metrics, views: views)
//If you want to set spacing or height and width with certain priority you can do that
let labelYConstraint = NSLayoutConstraint.constraintsWithVisualFormat("V:[topLabel]-(spacingBetweenMiddleLabelAndTopLabel#1000)-[middleLabel]-(spacingBetweenMiddleLabelAndBottomLabel#750)-[bottomtLabel]", options: [], metrics: metrics, views: views)
topLabel.addConstraints(heightTopLabel)
topLabel.addConstraints(widthTopLabel)
middleLabel.addConstraints(heightMiddleLabel)
middleLabel.addConstraints(widthMiddleLabel)
bottomtLabel.addConstraints(heightBottomLabel)
bottomtLabel.addConstraints(widthBottomLabel)
self.view.addConstraint(centreXMiddleLabel)
self.view.addConstraint(centreVMiddleLabel)
self.view.addConstraint(centreXTopLabel)
self.view.addConstraint(centreXBottomtLabel)
self.view.addConstraints(labelYConstraint)
Result after setting fixed points spacing between views:
The best solution would be to use auto layout but if you're going to stick with frames here's a bit of information.
Setting x and y in the frame will be overridden by changing the center point. If you'd like to achieve the positioning the best advice I could give in this situation would be something like. Untested but this might give you an idea.
Level = UILabel(frame: CGRect(x: 0, y: 0, width: 150, height: 100))
Level.center = (self.view?.center)!
Level.textAlignment = NSTextAlignment.Center
GeschwindigkeitUILabel = UILabel(frame: CGRect(x: 0, y: Level.frame.origin.y+Level.frame.size.height + PADDING, width: 300, height: 50))
GeschwindigkeitUILabel.center = CGPointMake(self.view?.center.x, GeschwindigkeitUILabel.center.y)
Regel = UILabel(frame: CGRect(x: 0, y: GeschwindigkeitUILabel.frame.origin.y+GeschwindigkeitUILabel.frame.size.height+ PADDING, width: 300, height: 50))
Regel.center = CGPointMake(self.view?.center.x, Regel.center.y)
I have a bunch of UIButtons that I want to space out evenly in a container view, right now I have this constraint for spacing:
someView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-(>=0)-[M]-(>=0)-[T]-(>=0)-[W]-(>=0)-[T]-(>=0)-[F]-(>=0)-[S]-(>=0)-[S]-(>=0)-|", options: NSLayoutFormatOptions.AlignAllCenterY, metrics: nil, views: buttonsArray))
However this makes the buttons look like this:
The problem is what I want for spacing is calculated in this way:
spacing = (someView.frame.width - (someView.frame.height * 0.6) * 7) / 8
someView.frame.height * 0.6 is the side length of the buttons. I am not sure what to do.
Here is a simple code which does exactly distribute the spaces between buttons in a view, I hope this will help you figure out for your use case,
let containerView = UIView(frame: CGRect.zero)
containerView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(containerView)
let M = UIButton(type: .System)
M.translatesAutoresizingMaskIntoConstraints = false
M.backgroundColor = UIColor.lightGrayColor()
M.setTitle("M", forState: .Normal)
containerView.addSubview(M)
let T = UIButton(type: .System)
T.translatesAutoresizingMaskIntoConstraints = false
T.setTitle("T", forState: .Normal)
T.backgroundColor = UIColor.lightGrayColor()
containerView.addSubview(T)
let W = UIButton(type: .System)
W.translatesAutoresizingMaskIntoConstraints = false
W.setTitle("W", forState: .Normal)
W.backgroundColor = UIColor.lightGrayColor()
containerView.addSubview(W)
let Th = UIButton(type: .System)
Th.translatesAutoresizingMaskIntoConstraints = false
Th.setTitle("T", forState: .Normal)
Th.backgroundColor = UIColor.lightGrayColor()
containerView.addSubview(Th)
let F = UIButton(type: .System)
F.translatesAutoresizingMaskIntoConstraints = false
F.setTitle("F", forState: .Normal)
F.backgroundColor = UIColor.lightGrayColor()
containerView.addSubview(F)
let S = UIButton(type: .System)
S.translatesAutoresizingMaskIntoConstraints = false
S.setTitle("S", forState: .Normal)
S.backgroundColor = UIColor.lightGrayColor()
containerView.addSubview(S)
let Su = UIButton(type: .System)
Su.translatesAutoresizingMaskIntoConstraints = false
Su.setTitle("Su", forState: .Normal)
Su.backgroundColor = UIColor.lightGrayColor()
containerView.addSubview(Su)
let views = [
"M": M,
"T": T,
"W": W,
"Th":Th,
"F": F,
"S": S,
"Su": Su
]
let horizontalSpacing = 20
let cornerMargin = 30
let metrics = [
"horizontalSpacing": horizontalSpacing,
"cornerMargin": cornerMargin
]
views.values.forEach { view in
view.clipsToBounds = true
view.layer.cornerRadius = 10
}
let verticalCenter = NSLayoutConstraint(item: containerView, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1.0, constant: 0)
let horizontalCenter = NSLayoutConstraint(item: containerView, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1.0, constant: 0)
view.addConstraint(verticalCenter)
view.addConstraint(horizontalCenter)
let horizontalFormat = "H:|-(==cornerMargin)-[M]-horizontalSpacing-[T]-horizontalSpacing-[W]-horizontalSpacing-[Th]-horizontalSpacing-[F]-horizontalSpacing-[S]-horizontalSpacing-[Su]-(==cornerMargin)-|"
let horizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat(horizontalFormat, options: .AlignAllCenterY, metrics: metrics, views: views)
view.addConstraints(horizontalConstraints)
let verticalFormat = "V:|-[M]-|"
let verticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat(verticalFormat, options: .AlignAllCenterY, metrics: metrics, views: views)
view.addConstraints(verticalConstraints)
And, here is the result,
Im working on an app and came across a problem that I cant seem to solve.
I am making a uiview with labels and images inside it. The content needs to be centered inside the view.
The problem is that the label will hold different lenght texts and the view itself will have different width depending on where it is used.
Here is how it should look:
And here with longer text:
As you can see there should be 1 label to the left, one uiimage in the middle and another label to the right all centered to the middle even though the text length could be different.
This is what I have so far in code. I need to do this programatically if possible. Im running a method to create the button depending on a value.
func cost(cost:Int){
costView = UIView()
costView?.setTranslatesAutoresizingMaskIntoConstraints(false)
self.costView?.clipsToBounds = true
self.addSubview(costView!)
self.costLabel.frame = CGRectMake(0, 0, 60, self.bounds.size.height)
self.costLabel.textAlignment = NSTextAlignment.Right
self.costLabel.textColor = UIColor.whiteColor()
self.costLabel.font = Services.exoFontWithSize(16)
self.costLabel.text = String(cost)
costView?.addSubview(costLabel)
self.costBrainImageView = UIImageView(frame: CGRectMake(0, 0, self.bounds.size.height, self.bounds.size.height))
self.costBrainImageView?.image = Graphics.maskImageNamed("CommonMediumBrain", color: UIColor.whiteColor())
self.costBrainImageView?.contentMode = UIViewContentMode.ScaleAspectFill
costView?.addSubview(costBrainImageView!)
self.label.adjustsFontSizeToFitWidth = true
self.label.setTranslatesAutoresizingMaskIntoConstraints(false)
self.label.numberOfLines = 1
self.label.minimumScaleFactor = 0.20
self.label.textAlignment = NSTextAlignment.Right
self.label.font = Services.exoFontWithSize(20)
//Constraints
var viewsDict = Dictionary <String, UIView>()
viewsDict["label"] = label
viewsDict["brainView"] = costView
self.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"V:|[label]|", options: nil, metrics: nil, views: viewsDict))
self.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"V:|[brainView]|", options: nil, metrics: nil, views: viewsDict))
self.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"H:|-[label]-5-[brainView]-|", options: NSLayoutFormatOptions.AlignAllCenterX, metrics: nil, views: viewsDict))
}
For the moment this breaks since this line
NSLayoutFormatOptions.AlignAllCenterX
'Unable to parse constraint format:
Options mask required views to be aligned on a horizontal edge, which is not allowed for layout that is also horizontal.
H:|-[label]-5-[brainView]-|
If i remove that everything is aligned to the left and not centered but im not sure this is the right way to accomplish what i want to do.
Any clues on how to solve this?
Thanks for any help
Firstly, change .AlignAllCenterX to .AlignAllCenterY, the reason is that"H:|-[label]-5-[brainView]-|" specifies how views position horizontally, you want label and brainView to have the same center Y position.
Secondly, make a subview that contains all 3 views, then center this subview inside the black rectangle. You can use costView as the subview.
Below is some modified code based on your existing code.
costView!.addSubview(label)
//Constraints
var viewsDict = Dictionary <String, UIView>()
viewsDict["label"] = label
viewsDict["brainView"] = costBrainImageView
viewsDict["costLabel"] = costLabel
costView!.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"V:|[label]|", options: nil, metrics: nil, views: viewsDict))
costView!.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"V:|[brainView]|", options: nil, metrics: nil, views: viewsDict))
costView!.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"V:|[costLabel]|", options: nil, metrics: nil, views: viewsDict))
costView!.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"H:|-[label]-5-[brainView]-5-[costLabel]-|", options: NSLayoutFormatOptions.AlignAllCenterY, metrics: nil, views: viewsDict))
costView!.backgroundColor = UIColor.redColor()
// center costView inside self
let centerXCons = NSLayoutConstraint(item: costView!, attribute: .CenterX, relatedBy: .Equal, toItem: self, attribute: .CenterX, multiplier: 1, constant: 0);
let centerYCons = NSLayoutConstraint(item: costView!, attribute: .CenterY, relatedBy: .Equal, toItem: self, attribute: .CenterY, multiplier: 1, constant: 0);
self.addConstraints([centerXCons, centerYCons])