iOS - View above all other views with Safe Area - ios

I would like to put a UIView above all other views. I saw that this is possible using the UIScreen object. However, it looks like the UIScreen doesn't have a Safe Area. This let's the View overlap with the Statusbar.
How can I place a View above all other Views while still using the Safe Area Insets?
I'm using this code in the Appdelegate's DidFinishLaunchingWithOptions():
window?.makeKeyAndVisible()
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.red
window?.addSubview(view)
window?.bringSubview(toFront: view)
let heightConstraint = NSLayoutConstraint(item: view, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 44)
view.addConstraint(heightConstraint)
let layoutGuide = window!.safeAreaLayoutGuide
let layoutGuideConstraints = [
view.topAnchor.constraint(equalTo: layoutGuide.topAnchor, constant: 8),
view.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor, constant: 8),
view.trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor, constant: -8)
]
NSLayoutConstraint.activate(layoutGuideConstraints)

Related

Positioning a button on bottom right of screen

I'm having trouble with the positioning of my button. I am trying to position my button on the bottom right of my screen. I am new with auto layouts. The button appears currently on the top left of the screen.
Here is my code:
add markers
add the map view
add the button
heres where I add markers:
func secondfunction() {
for x in names{
let url1 = URL(string: url: ", url1)
let data1 = try? Data(contentsOf: url1!) //make sure your image in this url does exist
//self.imagesOne = UIImage(data: data1!)
self.images.append(UIImage(data: data1!)!)
}
self.loadFunction()
}
heres where I load map and add button:
func loadFunction()
{
mapView = MGLMapView(frame: view.bounds)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mapView.centerCoordinate = CLLocationCoordinate2D(latitude:xCoord, longitude: yCoord)
mapView.zoomLevel = 15
mapView.delegate = self
view.addSubview(mapView)
var pointAnnotations = [MGLPointAnnotation]()
for coordinate in locationsList {
let location: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude)
let point = MGLPointAnnotation()
point.title = "Tap here"
point.coordinate = location
pointAnnotations.append(point)
}
self.tabBarController?.tabBar.isHidden = false
mapView.addAnnotations(pointAnnotations)
button.setBackgroundImage(UIImage(named:"compass.png"), for: .normal)
button.addTarget(self, action: #selector(btnPressed), for: UIControl.Event.touchUpInside)
self.view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
let widthContraints = NSLayoutConstraint(item: button, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 40)
let heightContraints = NSLayoutConstraint(item: button, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 40)
let xContraints = NSLayoutConstraint(item: button, attribute: NSLayoutConstraint.Attribute.bottomMargin, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.bottomMargin, multiplier: 1, constant: -80)
let yContraints = NSLayoutConstraint(item: button, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1, constant: -80)
NSLayoutConstraint.activate([heightContraints,widthContraints,xContraints,yContraints])
}
Give your button constraint to bottom
like this .. this is working tested code
override func viewDidLoad() {
super.viewDidLoad()
button.backgroundColor = .red
self.view.addSubview(button)
}
override func viewDidLayoutSubviews() {
button.translatesAutoresizingMaskIntoConstraints = false
let widthContraints = NSLayoutConstraint(item: button, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 40)
let heightContraints = NSLayoutConstraint(item: button, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 40)
let xContraints = NSLayoutConstraint(item: button, attribute: NSLayoutConstraint.Attribute.bottomMargin, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.bottomMargin, multiplier: 1, constant: -20)
let yContraints = NSLayoutConstraint(item: button, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1, constant: -20)
NSLayoutConstraint.activate([heightContraints,widthContraints,xContraints,yContraints])
}
if you want to position it right give it constraint from right margin
change constant according to your design preference
Remove this top constraint
let xContraints = NSLayoutConstraint(item: button, attribute: NSLayoutConstraint.Attribute.topMargin, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.topMargin, multiplier: 1, constant: 20)
and add a bottom constraint
NSLayoutConstraint.activate([
button.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: -20),
button.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -20),
button.widthAnchor.constraint(equalToConstant: 40),
button.heightAnchor.constraint(equalToConstant: 40)
])
It looks like you are doing constraints in code. If I may, could I offer a more recent alternative? Use anchors, which are much more easier and is part of any subclass of UIView.
There are several anchors for a view - top, bottom, left or leading, right or trailing, center x and Y, and height/width are the most used.
Now, for any view, you need to do two things:
Position it. In your case you only need to position your button in the (a) lower or bottom (b) right or trailing.
If it doesn't have an intrinsic size (search for a better definition than I can give) give your view a hight and width.
So in your case, lets say you wish to position a UIButton that is offset 10 points away from the bottom right of the screen. (Keep in mind that Apple has introduced "safe area insets" but that's a subject for another question. Again, search for it and you'll find lots of examples.)
button.translatesAutoresizingMaskIntoConstraints = false
Always remember to do this!
Now let's give your button a size:
button.widthAnchor.constraint(equalToConstant: 100).isActive = true
button.heightAnchor.constraint(equalToConstant: 50).isActive = true
Finally, position it:
button.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10).isActive = true
button.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10).isActive = true
That's it! The code is less verbose and thus easier to read.
Beyond the basics (and safe areas), you can also programmatically do two more things:
Change the constants (and for some views, the multiplier) as long as you name a constraint.
Selectively activate/deactivate an array of constraints, again, as long as you set them up in an array.
I find using anchors much easier, and have a different layout based on portrait or landscape by using arrays.

UIView not showing in UIViewcollection in Swift, Programmatically

the below code is the viewController that is navigated with a navigationItem navigationItem.leftBarButtonItem = UIBarButtonItem(title: from a previous tableViewController and I am trying to produce a UIView in my viewController. However nothing is showing.
import UIKit
class SecondpgController: UIViewController {
var inputContainerView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor .gray
let inputContainerView = UIView()
self.view.addSubview(inputContainerView)
//inputContainerView.backgroundColor = UIColor(red: 162/255, green: 20/255, blue: 35/255, alpha: 1)
inputContainerView.backgroundColor = .white
inputContainerView.translatesAutoresizingMaskIntoConstraints = false
//inputContainerView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 300).isActive = true
//nputContainerView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 10).isActive = true
inputContainerView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor, constant: 200).isActive = true
inputContainerView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: 200).isActive = true
The app is running well however after reaching the view controller, Nothing is shown but only a grey screen.
Why is this happening and how can I solve it?
Your problem is that you constraints are only setting x and y position for the UIView you are creating. You are missing width and height.
Try this constraints:
inputContainerView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
inputContainerView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
inputContainerView.widthAnchor.constraint(equalToConstant: 100).isActive = true
inputContainerView.heightAnchor.constraint(equalToConstant: 100).isActive = true
This code means that your UIView will be centred vertically and horizontally in your self.view and also it has a width and height of 100. It will look like this:
Hope it helps. Happy Coding
You have added constraints to place inputContainerView to the centre of the screen but did not add constraints for it's height and width. Adding the following code might solve your issue:
inputContainerView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor, constant: 0).isActive = true
inputContainerView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: 0).isActive = true
inputContainerView.addConstraint(NSLayoutConstraint(item: inputContainerView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 200))
inputContainerView.addConstraint(NSLayoutConstraint(item: inputContainerView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 200))
Check this: https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/ProgrammaticallyCreatingConstraints.html
Ensure that the constants for CenterXAnchor and CenterYAnchor are 0, so the view aligns at the centre. And make sure you add inputContainerView only once either as an outlet or programmatically.

How to make Constraints programmatically in iOS Swift 3.1? [duplicate]

I'm trying to figure this out since last week without going any step further. Ok, so I need to apply some constraints programmatically in Swift to a UIView using this code:
var new_view:UIView! = UIView(frame: CGRectMake(0, 0, 100, 100));
new_view.backgroundColor = UIColor.redColor();
view.addSubview(new_view);
var constX:NSLayoutConstraint = NSLayoutConstraint(item: new_view, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0);
self.view.addConstraint(constX);
var constY:NSLayoutConstraint = NSLayoutConstraint(item: new_view, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0);
self.view.addConstraint(constY);
var constW:NSLayoutConstraint = NSLayoutConstraint(item: new_view, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: new_view, attribute: NSLayoutAttribute.Width, multiplier: 1, constant: 0);
self.view.addConstraint(constW);
var constH:NSLayoutConstraint = NSLayoutConstraint(item: new_view, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: new_view, attribute: NSLayoutAttribute.Height, multiplier: 1, constant: 0);
self.view.addConstraint(constH);
But Xcode returns this weird output:
2014-10-03 09:48:12.657 Test[35088:2454916] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7fa4ea446830 UIView:0x7fa4ea429290.centerX == UIView:0x7fa4ea4470f0.centerX>",
"<NSAutoresizingMaskLayoutConstraint:0x7fa4ea4516c0 h=--& v=--& UIView:0x7fa4ea429290.midX == + 50>",
"<NSLayoutConstraint:0x7fa4ea452830 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7fa4ea4470f0(375)]>",
"<NSAutoresizingMaskLayoutConstraint:0x7fa4ea446db0 h=-&- v=-&- 'UIView-Encapsulated-Layout-Left' H:|-(0)-[UIView:0x7fa4ea4470f0] (Names: '|':UIWindow:0x7fa4ea444b20 )>"
)
Will attempt to recover by breaking constraint <NSLayoutConstraint:0x7fa4ea446830 UIView:0x7fa4ea429290.centerX == UIView:0x7fa4ea4470f0.centerX>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in
<UIKit/UIView.h> may also be helpful.
2014-10-03 09:48:12.658 Test[35088:2454916] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7fa4ea44d160 UIView:0x7fa4ea429290.centerY == UIView:0x7fa4ea4470f0.centerY>",
"<NSAutoresizingMaskLayoutConstraint:0x7fa4ea451b30 h=--& v=--& UIView:0x7fa4ea429290.midY == + 50>",
"<NSLayoutConstraint:0x7fa4ea44cf00 'UIView-Encapsulated-Layout-Height' V:[UIView:0x7fa4ea4470f0(667)]>",
"<NSAutoresizingMaskLayoutConstraint:0x7fa4ea452700 h=-&- v=-&- 'UIView-Encapsulated-Layout-Top' V:|-(0)-[UIView:0x7fa4ea4470f0] (Names: '|':UIWindow:0x7fa4ea444b20 )>"
)
Will attempt to recover by breaking constraint <NSLayoutConstraint:0x7fa4ea44d160 UIView:0x7fa4ea429290.centerY == UIView:0x7fa4ea4470f0.centerY>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
Can you help me?
Thanks a lot
Do you plan to have a squared UIView of width: 100 and Height: 100 centered inside the UIView of an UIViewController? If so, you may try one of the 6 following Auto Layout styles (Swift 5 / iOS 12.2):
1. Using NSLayoutConstraint initializer
override func viewDidLoad() {
let newView = UIView()
newView.backgroundColor = UIColor.red
view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0)
let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0)
let widthConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100)
let heightConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100)
view.addConstraints([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
}
override func viewDidLoad() {
let newView = UIView()
newView.backgroundColor = UIColor.red
view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0)
let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0)
let widthConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100)
let heightConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100)
NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
}
override func viewDidLoad() {
let newView = UIView()
newView.backgroundColor = UIColor.red
view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true
NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true
}
2. Using Visual Format Language
override func viewDidLoad() {
let newView = UIView()
newView.backgroundColor = UIColor.red
view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
let views = ["view": view!, "newView": newView]
let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[view]-(<=0)-[newView(100)]", options: NSLayoutConstraint.FormatOptions.alignAllCenterY, metrics: nil, views: views)
let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[view]-(<=0)-[newView(100)]", options: NSLayoutConstraint.FormatOptions.alignAllCenterX, metrics: nil, views: views)
view.addConstraints(horizontalConstraints)
view.addConstraints(verticalConstraints)
}
override func viewDidLoad() {
let newView = UIView()
newView.backgroundColor = UIColor.red
view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
let views = ["view": view!, "newView": newView]
let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[view]-(<=0)-[newView(100)]", options: NSLayoutConstraint.FormatOptions.alignAllCenterY, metrics: nil, views: views)
let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[view]-(<=0)-[newView(100)]", options: NSLayoutConstraint.FormatOptions.alignAllCenterX, metrics: nil, views: views)
NSLayoutConstraint.activate(horizontalConstraints)
NSLayoutConstraint.activate(verticalConstraints)
}
3. Using a mix of NSLayoutConstraint initializer and Visual Format Language
override func viewDidLoad() {
let newView = UIView()
newView.backgroundColor = UIColor.red
view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
let views = ["newView": newView]
let widthConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views)
let heightConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views)
let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0)
let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0)
view.addConstraints(widthConstraints)
view.addConstraints(heightConstraints)
view.addConstraints([horizontalConstraint, verticalConstraint])
}
override func viewDidLoad() {
let newView = UIView()
newView.backgroundColor = UIColor.red
view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
let views = ["newView": newView]
let widthConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views)
let heightConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views)
let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0)
let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0)
NSLayoutConstraint.activate(widthConstraints)
NSLayoutConstraint.activate(heightConstraints)
NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint])
}
override func viewDidLoad() {
let newView = UIView()
newView.backgroundColor = UIColor.red
view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
let views = ["newView": newView]
let widthConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views)
let heightConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views)
NSLayoutConstraint.activate(widthConstraints)
NSLayoutConstraint.activate(heightConstraints)
NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0).isActive = true
}
4. Using UIView.AutoresizingMask
Note: Springs and Struts will be translated into corresponding auto layout constraints at runtime.
override func viewDidLoad() {
let newView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
newView.backgroundColor = UIColor.red
view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = true
newView.center = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
newView.autoresizingMask = [UIView.AutoresizingMask.flexibleLeftMargin, UIView.AutoresizingMask.flexibleRightMargin, UIView.AutoresizingMask.flexibleTopMargin, UIView.AutoresizingMask.flexibleBottomMargin]
}
5. Using NSLayoutAnchor
override func viewDidLoad() {
let newView = UIView()
newView.backgroundColor = UIColor.red
view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
let horizontalConstraint = newView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
let verticalConstraint = newView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
let widthConstraint = newView.widthAnchor.constraint(equalToConstant: 100)
let heightConstraint = newView.heightAnchor.constraint(equalToConstant: 100)
view.addConstraints([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
}
override func viewDidLoad() {
let newView = UIView()
newView.backgroundColor = UIColor.red
view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
let horizontalConstraint = newView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
let verticalConstraint = newView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
let widthConstraint = newView.widthAnchor.constraint(equalToConstant: 100)
let heightConstraint = newView.heightAnchor.constraint(equalToConstant: 100)
NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
}
override func viewDidLoad() {
let newView = UIView()
newView.backgroundColor = UIColor.red
view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
newView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
newView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
newView.widthAnchor.constraint(equalToConstant: 100).isActive = true
newView.heightAnchor.constraint(equalToConstant: 100).isActive = true
}
6. Using intrinsicContentSize and NSLayoutAnchor
import UIKit
class CustomView: UIView {
override var intrinsicContentSize: CGSize {
return CGSize(width: 100, height: 100)
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
let newView = CustomView()
newView.backgroundColor = UIColor.red
view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
let horizontalConstraint = newView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
let verticalConstraint = newView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint])
}
}
Result:
It helps me to learn visually, so this is a supplemental answer.
Boilerplate code
override func viewDidLoad() {
super.viewDidLoad()
let myView = UIView()
myView.backgroundColor = UIColor.blue
myView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(myView)
// Add constraints code here
// ...
}
Each of the following examples are independent of the others.
Pin left edge
myView.leading = leadingMargin + 20
Method 1: Anchor Style
let margins = view.layoutMarginsGuide
myView.leadingAnchor.constraint(equalTo: margins.leadingAnchor, constant: 20).isActive = true
In addition to leadingAnchor, there is also trailingAnchor, topAnchor, and bottomAnchor.
Method 2: NSLayoutConstraint Style
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.leadingMargin, multiplier: 1.0, constant: 20.0).isActive = true
In addition to .leading there is also .trailing, .top, and .bottom.
In addition to .leadingMargin there is also .trailingMargin, .topMargin, and .bottomMargin.
Set Width and Height
width = 200
height = 100
Method 1: Anchor Style
myView.widthAnchor.constraint(equalToConstant: 200).isActive = true
myView.heightAnchor.constraint(equalToConstant: 100).isActive = true
Method 2: NSLayoutConstraint Style
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 200).isActive = true
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true
Center in container
myView.centerX = centerX
myView.centerY = centerY
Method 1: Anchor Style
myView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
myView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
Method 2: NSLayoutConstraint Style
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0).isActive = true
Notes
Anchor style is the preferred method over NSLayoutConstraint Style, however it is only available from iOS 9, so if you are supporting iOS 8 then you should still use NSLayoutConstraint Style.
The examples above showed just the one or two constraints that were being focused on. However, in order to properly place myView in my test project I needed to have four constraints.
Further Reading
Programmatically Creating Constraints documentation
If you want to fill your super view then I suggest the swifty way:
view.translatesAutoresizingMaskIntoConstraints = false
let attributes: [NSLayoutAttribute] = [.top, .bottom, .right, .left]
NSLayoutConstraint.activate(attributes.map {
NSLayoutConstraint(item: view, attribute: $0, relatedBy: .equal, toItem: view.superview, attribute: $0, multiplier: 1, constant: 0)
})
Other wise if you need non equal constraints check out NSLayoutAnchor as of iOS 9. Its often much easier to read that using NSLayoutConstraint directly:
view.translatesAutoresizingMaskIntoConstraints = false
view.topAnchor.constraint(equalTo: view.superview!.topAnchor).isActive = true
view.bottomAnchor.constraint(equalTo: view.superview!.bottomAnchor).isActive = true
view.leadingAnchor.constraint(equalTo: view.superview!.leadingAnchor, constant: 10).isActive = true
view.trailingAnchor.constraint(equalTo: view.superview!.trailingAnchor, constant: 10).isActive = true
We can easily do this with in swift 5.1
setup 1
subview align to view center
subview width height set using float
view.addSubview(myView1)
myView1.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
myView1.centerXAnchor.constraint(equalTo: view.centerXAnchor),
myView1.centerYAnchor.constraint(equalTo: view.centerYAnchor),
myView1.widthAnchor.constraint(equalToConstant: 100),
myView1.heightAnchor.constraint(equalToConstant: 100),
])
setup 2
subview align to view leading and top anchor
subview width set using view width height
view.addSubview(myView2)
myView2.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
myView2.leadingAnchor.constraint(equalTo: view.leadingAnchor,constant: 16),
myView2.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor,constant: 16),
myView2.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.3),
myView2.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.3)
])
Constraints for multiple views in playground.
swift 3+
var yellowView: UIView!
var redView: UIView!
override func loadView() {
// UI
let view = UIView()
view.backgroundColor = .white
yellowView = UIView()
yellowView.backgroundColor = .yellow
view.addSubview(yellowView)
redView = UIView()
redView.backgroundColor = .red
view.addSubview(redView)
// Layout
redView.translatesAutoresizingMaskIntoConstraints = false
yellowView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
yellowView.topAnchor.constraint(equalTo: view.topAnchor, constant: 20),
yellowView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
yellowView.widthAnchor.constraint(equalToConstant: 80),
yellowView.heightAnchor.constraint(equalToConstant: 80),
redView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20),
redView.trailingAnchor.constraint(equalTo: view.trailingAnchor,constant: -20),
redView.widthAnchor.constraint(equalToConstant: 80),
redView.heightAnchor.constraint(equalToConstant: 80)
])
self.view = view
}
In my opinion xcode playground is the best place for learning adding
constraints programmatically.
Basically it involved 3 steps
fileprivate func setupName() {
lblName.text = "Hello world"
// Step 1
lblName.translatesAutoresizingMaskIntoConstraints = false
//Step 2
self.view.addSubview(lblName)
//Step 3
NSLayoutConstraint.activate([
lblName.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
lblName.centerYAnchor.constraint(equalTo: self.view.centerYAnchor)
])
}
This puts label "hello world" in center of screen.
Please refer link Autolayout constraints programmatically
The problem, as the error message suggests, is that you have constraints of type NSAutoresizingMaskLayoutConstraints that conflict with your explicit constraints, because new_view.translatesAutoresizingMaskIntoConstraints is set to true.
This is the default setting for views you create in code. You can turn it off like this:
var new_view:UIView! = UIView(frame: CGRectMake(0, 0, 100, 100))
new_view.translatesAutoresizingMaskIntoConstraints = false
Also, your width and height constraints are weird. If you want the view to have a constant width, this is the proper way:
new_view.addConstraint(NSLayoutConstraint(
item:new_view, attribute:NSLayoutAttribute.Width,
relatedBy:NSLayoutRelation.Equal,
toItem:nil, attribute:NSLayoutAttribute.NotAnAttribute,
multiplier:0, constant:100))
(Replace 100 by the width you want it to have.)
If your deployment target is iOS 9.0 or later, you can use this shorter code:
new_view.widthAnchor.constraintEqualToConstant(100).active = true
Anyway, for a layout like this (fixed size and centered in parent view), it would be simpler to use the autoresizing mask and let the system translate the mask into constraints:
var new_view:UIView! = UIView(frame: CGRectMake(0, 0, 100, 100))
new_view.backgroundColor = UIColor.redColor();
view.addSubview(new_view);
// This is the default setting but be explicit anyway...
new_view.translatesAutoresizingMaskIntoConstraints = true
new_view.autoresizingMask = [ .FlexibleTopMargin, .FlexibleBottomMargin,
.FlexibleLeftMargin, .FlexibleRightMargin ]
new_view.center = CGPointMake(view.bounds.midX, view.bounds.midY)
Note that using autoresizing is perfectly legitimate even when you're also using autolayout. (UIKit still uses autoresizing in lots of places internally.) The problem is that it's difficult to apply additional constraints to a view that is using autoresizing.
Updated for Swift 3
import UIKit
class ViewController: UIViewController {
let redView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .red
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
setupAutoLayout()
}
func setupViews() {
view.backgroundColor = .white
view.addSubview(redView)
}
func setupAutoLayout() {
// Available from iOS 9 commonly known as Anchoring System for AutoLayout...
redView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
redView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20).isActive = true
redView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
redView.heightAnchor.constraint(equalToConstant: 300).isActive = true
// You can also modified above last two lines as follows by commenting above & uncommenting below lines...
// redView.topAnchor.constraint(equalTo: view.topAnchor, constant: 20).isActive = true
// redView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
}
Type of Constraints
/*
// regular use
1.leftAnchor
2.rightAnchor
3.topAnchor
// intermediate use
4.widthAnchor
5.heightAnchor
6.bottomAnchor
7.centerXAnchor
8.centerYAnchor
// rare use
9.leadingAnchor
10.trailingAnchor
etc. (note: very project to project)
*/
Auto layout is realized by applying constraints on images. Use NSLayoutConstraint. It is possible to implement an ideal and beautiful design on all devices. Please try the code below.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let myImageView:UIImageView = UIImageView()
myImageView.backgroundColor = UIColor.red
myImageView.image = UIImage(named:"sample_dog")!
myImageView.translatesAutoresizingMaskIntoConstraints = false
myImageView.layer.borderColor = UIColor.red.cgColor
myImageView.layer.borderWidth = 10
self.view.addSubview(myImageView)
view.removeConstraints(view.constraints)
view.addConstraint(NSLayoutConstraint(
item: myImageView,
attribute: .top,
relatedBy: .equal,
toItem: view,
attribute: .top,
multiplier: 1,
constant:100)
)
view.addConstraint(NSLayoutConstraint(
item: myImageView,
attribute: .centerX,
relatedBy: .equal,
toItem: view,
attribute: .centerX,
multiplier: 1,
constant:0)
)
view.addConstraint(NSLayoutConstraint(
item: myImageView,
attribute: .height,
relatedBy: .equal,
toItem: view,
attribute: .width,
multiplier: 0.5,
constant:40))
view.addConstraint(NSLayoutConstraint(
item: myImageView,
attribute: .width,
relatedBy: .equal,
toItem: view,
attribute: .width,
multiplier: 0.5,
constant:40))
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
the following code works for me in this scenario: an UIImageView forced landscape.
imagePreview!.isUserInteractionEnabled = true
imagePreview!.isExclusiveTouch = true
imagePreview!.contentMode = UIView.ContentMode.scaleAspectFit
// Remove all constraints
imagePreview!.removeAllConstraints()
// Add the new constraints
let guide = view.safeAreaLayoutGuide
imagePreview!.translatesAutoresizingMaskIntoConstraints = false
imagePreview!.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true
imagePreview!.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true
imagePreview!.heightAnchor.constraint(equalTo: guide.heightAnchor, multiplier: 1.0).isActive = true
where removeAllConstraints is an extension
extension UIView {
func removeAllConstraints() {
var _superview = self.superview
func removeAllConstraintsFromView(view: UIView) { for c in view.constraints { view.removeConstraint(c) } }
while let superview = _superview {
for constraint in superview.constraints {
if let first = constraint.firstItem as? UIView, first == self {
superview.removeConstraint(constraint)
}
if let second = constraint.secondItem as? UIView, second == self {
superview.removeConstraint(constraint)
}
}
_superview = superview.superview
}
self.removeConstraints(self.constraints)
self.translatesAutoresizingMaskIntoConstraints = true
}
}
If you find the above to be ugly. You should consider using a DSL for constraints. Such as SnapKit
Makes constraint API much more user-friendly
view.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
Would like to add some theoretical concept to Imanou Petit’s answer, so that one can understand how auto layout works.
To understand auto layout consider your view as rubber's object which is shrinked initially.
To place an object on screen we need 4 mandatory things :
X coordinate of object (horizontal position).
Y coordinate of object (vertical position )
Object’s Width
Object’s Height.
1 X coordinate: There are multiple ways of giving x coordinates to a view.
Such as Leading constraint, Trailing constraint , Horizontally centre
etc.
2 Y coordinate: There are multiple ways of giving y coordinates to a view :
Such as Top constraint, Bottom constraint , Vertical centre etc.
3 Object's width: There are two ways of giving width constrain to a view :
a. Add fixed width constraint (consider this constraint as iron rod of fixed width and you have hooked your rubber’s object horizontally with it so rubber’s object don’t shrink or expand)
b. Do not add any width constraint but add x coordinate constraint to both end of view trailing and leading, these two constraints will expand/shrink your rubber’s object by pulling/pushing it from both end, leading and trailing.
4 Object's height: Similar to width, there are two ways of giving height constraint to a view as well :
a. Add fixed height constraint (consider this constraints as iron rod of fixed height and you have hooked your rubber’s object vertically with it so rubber’s object don’t shrink or expand)
b. Do not add any height constraint but add x coordinate constraint to both end of view top and bottom, these two constraints will expand/shrink your rubber’s object pulling/pushing it from both end, top and bottom.
it is a little different in xcode 7.3.1. this is what i come up with
// creating the view
let newView = UIView()
newView.backgroundColor = UIColor.redColor()
newView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(newView)
// creating the constraint
// attribute and relation cannot be set directyl you need to create a cariable of them
let layout11 = NSLayoutAttribute.CenterX
let layout21 = NSLayoutRelation.Equal
let layout31 = NSLayoutAttribute.CenterY
let layout41 = NSLayoutAttribute.Width
let layout51 = NSLayoutAttribute.Height
let layout61 = NSLayoutAttribute.NotAnAttribute
// defining all the constraint
let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: layout11, relatedBy: layout21, toItem: view, attribute: layout11, multiplier: 1, constant: 0)
let verticalConstraint = NSLayoutConstraint(item: newView, attribute: layout31, relatedBy: layout21, toItem: view, attribute: layout31, multiplier: 1, constant: 0)
let widthConstraint = NSLayoutConstraint(item: newView, attribute: layout41, relatedBy: layout21, toItem: nil, attribute: layout61, multiplier: 1, constant: 100)
let heightConstraint = NSLayoutConstraint(item: newView, attribute: layout51, relatedBy: layout21, toItem: nil, attribute: layout61, multiplier: 1, constant: 100)
// adding all the constraint
NSLayoutConstraint.activateConstraints([horizontalConstraint,verticalConstraint,widthConstraint,heightConstraint])
This is one way to adding constraints programmatically
override func viewDidLoad() {
super.viewDidLoad()
let myLabel = UILabel()
myLabel.labelFrameUpdate(label: myLabel, text: "Welcome User", font: UIFont(name: "times new roman", size: 40)!, textColor: UIColor.red, textAlignment: .center, numberOfLines: 0, borderWidth: 2.0, BorderColor: UIColor.red.cgColor)
self.view.addSubview(myLabel)
let myLabelhorizontalConstraint = NSLayoutConstraint(item: myLabel, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0)
let myLabelverticalConstraint = NSLayoutConstraint(item: myLabel, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0)
let mylabelLeading = NSLayoutConstraint(item: myLabel, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.leading, multiplier: 1, constant: 10)
let mylabelTrailing = NSLayoutConstraint(item: myLabel, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.trailing, multiplier: 1, constant: -10)
let myLabelheightConstraint = NSLayoutConstraint(item: myLabel, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 50)
NSLayoutConstraint.activate(\[myLabelhorizontalConstraint, myLabelverticalConstraint, myLabelheightConstraint,mylabelLeading,mylabelTrailing\])
}
extension UILabel
{
func labelFrameUpdate(label:UILabel,text:String = "This is sample Label",font:UIFont = UIFont(name: "times new roman", size: 20)!,textColor:UIColor = UIColor.red,textAlignment:NSTextAlignment = .center,numberOfLines:Int = 0,borderWidth:CGFloat = 2.0,BorderColor:CGColor = UIColor.red.cgColor){
label.translatesAutoresizingMaskIntoConstraints = false
label.text = text
label.font = font
label.textColor = textColor
label.textAlignment = textAlignment
label.numberOfLines = numberOfLines
label.layer.borderWidth = borderWidth
label.layer.borderColor = UIColor.red.cgColor
}
}
var xCenterConstraint : NSLayoutConstraint!
var yCenterConstraint: NSLayoutConstraint!
xCenterConstraint = NSLayoutConstraint(item: self.view, attribute: .CenterX, relatedBy: .Equal, toItem: (Your view NAme), attribute: .CenterX, multiplier: 1, constant: 0)
self.view.addConstraint(xCenterConstraint)
yCenterConstraint = NSLayoutConstraint(item: self.view, attribute: .CenterY, relatedBy: .Equal, toItem: (Your view Name), attribute: .CenterY, multiplier: 1, constant: 0)
self.view.addConstraint(yCenterConstraint)
Try this elegant UIView extension for constraints. You can do constraints easy as:
- firstView.coverWholeSuperview()
- firstView.constraints(size: CGSize(width: 44, height: 44), centerX: view.centerXAnchor, centerY: view.centerXAnchor)
- firstView.constraints(top: view.topAnchor,
leading: secondView.leadingAnchor,
bottom: view.bottomAnchor,
trailing: secondView.trailingAnchor,
padding: UIEdgeInsets(top: 12, left: 12, bottom: 12, right: 12))
Here is extension, just copy it to your project.
extension UIView {
/// Attaches all sides of the receiver to its parent view
func coverWholeSuperview(margin: CGFloat = 0.0) {
let view = superview
layoutAttachTop(to: view, margin: margin)
layoutAttachBottom(to: view, margin: margin)
layoutAttachLeading(to: view, margin: margin)
layoutAttachTrailing(to: view, margin: margin)
}
/// Attaches the top of the current view to the given view's top if it's a superview of the current view
/// or to it's bottom if it's not (assuming this is then a sibling view).
#discardableResult
func layoutAttachTop(to: UIView? = nil, margin: CGFloat = 0.0) -> NSLayoutConstraint {
let view: UIView? = to ?? superview
let isSuperview = view == superview
let constraint = NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal,
toItem: view, attribute: isSuperview ? .top : .bottom, multiplier: 1.0,
constant: margin)
superview?.addConstraint(constraint)
return constraint
}
/// Attaches the bottom of the current view to the given view
#discardableResult
func layoutAttachBottom(to: UIView? = nil, margin: CGFloat = 0.0, priority: UILayoutPriority? = nil) -> NSLayoutConstraint {
let view: UIView? = to ?? superview
let isSuperview = (view == superview) || false
let constraint = NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal,
toItem: view, attribute: isSuperview ? .bottom : .top, multiplier: 1.0,
constant: -margin)
if let priority = priority {
constraint.priority = priority
}
superview?.addConstraint(constraint)
return constraint
}
/// Attaches the leading edge of the current view to the given view
#discardableResult
func layoutAttachLeading(to: UIView? = nil, margin: CGFloat = 0.0) -> NSLayoutConstraint {
let view: UIView? = to ?? superview
let isSuperview = (view == superview) || false
let constraint = NSLayoutConstraint(item: self, attribute: .leading, relatedBy: .equal,
toItem: view, attribute: isSuperview ? .leading : .trailing, multiplier: 1.0,
constant: margin)
superview?.addConstraint(constraint)
return constraint
}
/// Attaches the trailing edge of the current view to the given view
#discardableResult
func layoutAttachTrailing(to: UIView? = nil, margin: CGFloat = 0.0, priority: UILayoutPriority? = nil) -> NSLayoutConstraint {
let view: UIView? = to ?? superview
let isSuperview = (view == superview) || false
let constraint = NSLayoutConstraint(item: self, attribute: .trailing, relatedBy: .equal,
toItem: view, attribute: isSuperview ? .trailing : .leading, multiplier: 1.0,
constant: -margin)
if let priority = priority {
constraint.priority = priority
}
superview?.addConstraint(constraint)
return constraint
}
// For anchoring View
struct AnchoredConstraints {
var top, leading, bottom, trailing, width, height, centerX, centerY: NSLayoutConstraint?
}
#discardableResult
func constraints(top: NSLayoutYAxisAnchor? = nil, leading: NSLayoutXAxisAnchor? = nil, bottom: NSLayoutYAxisAnchor? = nil,
trailing: NSLayoutXAxisAnchor? = nil, padding: UIEdgeInsets = .zero, size: CGSize = .zero,
centerX: NSLayoutXAxisAnchor? = nil, centerY: NSLayoutYAxisAnchor? = nil,
centerXOffset: CGFloat = 0, centerYOffset: CGFloat = 0) -> AnchoredConstraints {
translatesAutoresizingMaskIntoConstraints = false
var anchoredConstraints = AnchoredConstraints()
if let top = top {
anchoredConstraints.top = topAnchor.constraint(equalTo: top, constant: padding.top)
}
if let leading = leading {
anchoredConstraints.leading = leadingAnchor.constraint(equalTo: leading, constant: padding.left)
}
if let bottom = bottom {
anchoredConstraints.bottom = bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom)
}
if let trailing = trailing {
anchoredConstraints.trailing = trailingAnchor.constraint(equalTo: trailing, constant: -padding.right)
}
if size.width != 0 {
anchoredConstraints.width = widthAnchor.constraint(equalToConstant: size.width)
}
if size.height != 0 {
anchoredConstraints.height = heightAnchor.constraint(equalToConstant: size.height)
}
if let centerX = centerX {
anchoredConstraints.centerX = centerXAnchor.constraint(equalTo: centerX, constant: centerXOffset)
}
if let centerY = centerY {
anchoredConstraints.centerY = centerYAnchor.constraint(equalTo: centerY, constant: centerYOffset)
}
[anchoredConstraints.top, anchoredConstraints.leading, anchoredConstraints.bottom,
anchoredConstraints.trailing, anchoredConstraints.width,
anchoredConstraints.height, anchoredConstraints.centerX,
anchoredConstraints.centerY].forEach { $0?.isActive = true }
return anchoredConstraints
}
}
You are adding all defined constraints to self.view which is wrong, as width and height constraint should be added to your newView.
Also, as I understand you want to set constant width and height 100:100.
In this case you should change your code to:
var constW = NSLayoutConstraint(item: newView,
attribute: .Width,
relatedBy: .Equal,
toItem: nil,
attribute: .NotAnAttribute,
multiplier: 1,
constant: 100)
newView.addConstraint(constW)
var constH = NSLayoutConstraint(item: newView,
attribute: .Height,
relatedBy: .Equal,
toItem: nil,
attribute: .NotAnAttribute,
multiplier: 1,
constant: 100)
newView.addConstraint(constH)
You can use Snapkit to set constraints programmatically.
class ViewController: UIViewController {
let rectView: UIView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
}
private func setupViews() {
rectView.backgroundColor = .red
view.addSubview(rectView)
rectView.snp.makeConstraints {
$0.center.equalToSuperview()
}
}
}
The error is caused by constrains automatically created from autoresizing mask, they are created because UIView property translatesAutoresizingMaskIntoConstraints is true by default.
Consider using BoxView to get rid of all manual constraint creation boilerplate, and make your code concize and readable. To make layout in question with BoxView is very easy:
boxView.items = [
new_view.boxed.centerX().centerY().relativeWidth(1.0).relativeHeight(1.0)
]

Add Constraint to navigationBar Programmatically Swift

I'm trying to add constraint to navigation bar, I have UIImageView, which has width, height and is centered horizontally, I want to add vertical space between UIImage and navigationBar to 0, I'm trying this for like 1 hour and couldn't figure out how, i tried adding constraint to UIView, and added constant of navbarHeight + statusBarHeight, and it worked, but I want to make relationship between imageview and navbar
let verticalSpace = NSLayoutConstraint(item: image, attribute: .Top, relatedBy: .Equal, toItem: self.view, attribute: .Top, multiplier: 1, constant: 0)
view.addConstraint(verticalSpace) // this works
try with topLayoutGuide
let verticalSpace = NSLayoutConstraint(item: image,
attribute: .Top,
relatedBy: .Equal,
toItem: self.topLayoutGuide,
attribute: .Bottom,
multiplier: 1, constant: 0)
The above constraint explanation:
simply its called: vertical space between image.Top & self.topLayoutGuide.Bottom = 0
that means Top constraint of image view attached with a Bottom attribute of topLayoutGuide with constant 0.
You can use anchors as well to make this possible for iOS 10+
if #available(iOS 11.0, *) {
image.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
} else {
image.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor).isActive = true
}
llkenny's answer for iOS 11.0+ :
image.topAnchor.constraint(equalTo:
view.safeAreaLayoutGuide.topAnchor).isActive = true
With anchors:
image.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor).isActive = true
In storyboard. Two constraints:
The first:
The second:
Result:
code:
func mainCollectionViewConstraint() {
NSLayoutConstraint.activate([
mainCollectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10),
mainCollectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
mainCollectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
mainCollectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
])
}

Autolayout Resize UIView Not Working

I am attempting to get a UIView courseView to autolayout. I would like to have the proportions of the UIView remain and fill up until the outermost edges are 15 point from the edge of the superview.
For some reason courseView fills the entire superview (minus the 15 points) and does not resize to fit. So some of it does not show and is cut off.
self.view.addSubview(courseView!)
let aspectConstraint = NSLayoutConstraint(item: courseView,
attribute: .Height,
relatedBy: .Equal,
toItem: courseView,
attribute: .Width,
multiplier: courseView.frame.size.height / courseView.frame.size.width,
constant: 0.0)
aspectConstraint.active = true
let topConstraint = courseView.topAnchor.constraintGreaterThanOrEqualToAnchor(topLayoutGuide.bottomAnchor, constant: 15)
topConstraint.active = true
let leadingConstraint = courseView.leadingAnchor.constraintLessThanOrEqualToAnchor(view.leadingAnchor, constant: 15)
leadingConstraint.active = true
let trailingConstraint = courseView.trailingAnchor.constraintGreaterThanOrEqualToAnchor(view.trailingAnchor, constant: -15)
trailingConstraint.active = true
let bottomConstraint = courseView.bottomAnchor.constraintLessThanOrEqualToAnchor(view.bottomAnchor, constant: -15)
bottomConstraint.active = true
Any ideas? Thanks!
Just disable translatesAutoresizingMaskIntoConstraints before adding the constraints and it should work just fine.
courseView.translatesAutoresizingMaskIntoConstraints = false;
And by the way, you do not need the aspectConstraint because that will most probably break the constratints (it did for me, when I tried).

Resources