custom keyboard landscape don't show right - ios

when I want to active landscape for my custom keyboard, I set new constraint for them. but I don't know why the landscape isn't been show rightly. the protrait is good, but the landscape is not. some one can help?
Xcode Version: Version 13.4.1 (13F100)
Swift Version: 5
LandScape is not right
override func viewDidLoad() {
super.viewDidLoad()
// Perform custom UI setup here
shiftStatus = 0
deleteletters = 0// disable autoresize
view.translatesAutoresizingMaskIntoConstraints = false
if(preferredInterfaceOrientationForPresentation.isPortrait) {
//set row protrait height
RowA0.heightAnchor.constraint(equalToConstant: 45).isActive = true
RowA1.heightAnchor.constraint(equalToConstant: 50).isActive = true
RowA2.heightAnchor.constraint(equalToConstant: 50).isActive = true
RowA3.heightAnchor.constraint(equalToConstant: 50).isActive = true
RowA4.heightAnchor.constraint(equalToConstant: 45).isActive = true
RowB1.heightAnchor.constraint(equalToConstant: 50).isActive = true
RowB2.heightAnchor.constraint(equalToConstant: 50).isActive = true
RowB3.heightAnchor.constraint(equalToConstant: 50).isActive = true
RowC1.heightAnchor.constraint(equalToConstant: 50).isActive = true
RowC2.heightAnchor.constraint(equalToConstant: 50).isActive = true
//change keybaord protrait hight
let heightconstraint = NSLayoutConstraint(item: self.view as Any,
attribute: .height,
relatedBy: .equal,
toItem: nil,
attribute: .notAnAttribute,
multiplier: 0.0,
constant: 255) // Set custom height here
self.view.addConstraint(heightconstraint)
//change keybaord protrait width
let widthconstraint = NSLayoutConstraint(item: self.view as Any,
attribute: .width,
relatedBy: .equal,
toItem: nil,
attribute: .notAnAttribute,
multiplier: 0.0,
constant: 428) // Set custom height here
self.view.addConstraint(widthconstraint)
}
if(preferredInterfaceOrientationForPresentation.isLandscape) {
//set row landscape height
RowA0.heightAnchor.constraint(equalToConstant: 30).isActive = true
RowA1.heightAnchor.constraint(equalToConstant: 30).isActive = true
RowA2.heightAnchor.constraint(equalToConstant: 30).isActive = true
RowA3.heightAnchor.constraint(equalToConstant: 30).isActive = true
RowA4.heightAnchor.constraint(equalToConstant: 30).isActive = true
RowB1.heightAnchor.constraint(equalToConstant: 30).isActive = true
RowB2.heightAnchor.constraint(equalToConstant: 30).isActive = true
RowB3.heightAnchor.constraint(equalToConstant: 30).isActive = true
RowC1.heightAnchor.constraint(equalToConstant: 30).isActive = true
RowC2.heightAnchor.constraint(equalToConstant: 30).isActive = true
//change keybaord landscape hight
let heightconstraint = NSLayoutConstraint(item: self.view as Any,
attribute: .height,
relatedBy: .equal,
toItem: nil,
attribute: .notAnAttribute,
multiplier: 0.0,
constant: 170) // Set custom height here
self.view.addConstraint(heightconstraint)
//change keybaord landscape width
let widthconstraint = NSLayoutConstraint(item: self.view as Any,
attribute: .width,
relatedBy: .equal,
toItem: nil,
attribute: .notAnAttribute,
multiplier: 0.0,
constant: 838) // Set custom height here
self.view.addConstraint(widthconstraint)
}
}

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.

How can I add text in the center of a UIView Programmatically?

I have the following UIView, how can text be added in the center of this UIView programmatically?
This is the UIView code:
let newView = UIView()
newView.backgroundColor = .groupTableViewBackground
self.view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
if #available(iOS 11.0, *) {
let guide = self.view.safeAreaLayoutGuide
newView.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true
newView.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true
newView.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true
newView.heightAnchor.constraint(equalToConstant: 50).isActive = true
} else {
NSLayoutConstraint(item: newView,
attribute: .top,
relatedBy: .equal,
toItem: view, attribute: .top,
multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: newView,
attribute: .leading,
relatedBy: .equal, toItem: view,
attribute: .leading,
multiplier: 1.0,
constant: 0).isActive = true
NSLayoutConstraint(item: newView, attribute: .trailing,
relatedBy: .equal,
toItem: view,
attribute: .trailing,
multiplier: 1.0,
constant: 0).isActive = true
newView.heightAnchor.constraint(equalToConstant: 50).isActive = true
}
This was my attempt at adding text to the center of the UIView programmatically, but I'm not sure why it is not working?
let lb = UILabel()
lb.centerXAnchor.constraint(equalTo: newView.centerXAnchor).isActive = true
lb.centerYAnchor.constraint(equalTo: newView.centerYAnchor).isActive = true
lb.text="anything"
newView.backgroundColor = UIColor.white
// show on screen
self.view.addSubview(newView)
newView.addSubview(lb)
lb.center = newView.center
UPDATE:
How can this button border below the UIView that's under the navigation controller be added?
When it comes to adding constraints to the view programmatically, note that you have to set translatesAutoresizingMaskIntoConstraints to false (but I get the feeling that you already know this, and just forgot to add it to the label)
let lb = UILabel()
lb.textAlignment = .center
lb.numberOfLines = 0
newView.addSubview(lb)
lb.translatesAutoresizingMaskIntoConstraints = false
lb.centerXAnchor.constraint(equalTo: newView.centerXAnchor).isActive = true
lb.centerYAnchor.constraint(equalTo: newView.centerYAnchor).isActive = true
Add border (assuming you want to add the border to the newView):
let border = UIView()
newView.addSubview(border)
border.translatesAutoresizingMaskIntoConstraints = false
border.leadingAnchor.constraint(equalTo: newView.leadingAnchor).isActive = true
border.trailingAnchor.constraint(equalTo: newView.trailingAnchor).isActive = true
border.bottomAnchor.constraint(equalTo: newView.bottomAnchor).isActive = true
border.heightAnchor.constraint(equalToConstant: 1).isActive = true
But for the border it would probably be cleaner to write an extension on UIView, so the code can be reusable in other places, if you ever need it again

How to add subView to anotherSubView with center alignment in iOS swift.

I'm using lottie library for animation. I loaded lottieFile as subView to anotherSubView but it's not aligned in center. I tried using center attributes as below:
#IBOutlet weak var viewOn: UIView!
let animationView = LOTAnimationView(name: "restless_gift_ii") {
animationView.loopAnimation = true
animationView.contentMode = .scaleToFill
animationView.animationSpeed = 1
animationView.backgroundColor = UIColor.black
animationView.frame.size = viewOn.frame.size
animationView.center.x = viewOn.center.x
animationView.center.y = viewOn.center.y
viewOn.addSubview(animationView) }
You can use auto layout programmatically to center align your animation view into it’s super view.
Here, I have added two ways to add animationView center align and also added comments for understanding.
if let animationView = LOTAnimationView(name: "4_bar_loop") {
animationView.loopAnimation = true
animationView.contentMode = .scaleToFill
animationView.animationSpeed = 1
animationView.backgroundColor = UIColor.black
self.viewOn.addSubview(animationView)
animationView.translatesAutoresizingMaskIntoConstraints = false
// Apply these constrains if you want animation size should be same as super view.
self.viewOn.addConstraint(NSLayoutConstraint(item: animationView, attribute: .leading, relatedBy: .equal, toItem: self.viewOn, attribute: .leading, multiplier: 1.0, constant: 1))
self.viewOn.addConstraint(NSLayoutConstraint(item: animationView, attribute: .trailing, relatedBy: .equal, toItem: self.viewOn, attribute: .trailing, multiplier: 1.0, constant: 1))
self.viewOn.addConstraint(NSLayoutConstraint(item: animationView, attribute: .top, relatedBy: .equal, toItem: self.viewOn, attribute:.top, multiplier: 1.0, constant: 1))
self.viewOn.addConstraint(NSLayoutConstraint(item: animationView, attribute: .bottom, relatedBy: .equal, toItem: self.viewOn, attribute: .bottom, multiplier: 1.0, constant: 1))
// Apply these constraint if you want animationView with fixed height and width and center of super view.
// self.viewOn.addConstraint(NSLayoutConstraint(item: animationView, attribute: .centerX, relatedBy: .equal, toItem: self.viewOn, attribute: .centerX, multiplier: 1.0, constant: 1))
// self.viewOn.addConstraint(NSLayoutConstraint(item: animationView, attribute: .centerY, relatedBy: .equal, toItem: self.viewOn, attribute: .centerY, multiplier: 1.0, constant: 1))
// animationView.addConstraint(NSLayoutConstraint(item: animationView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 100))
// animationView.addConstraint(NSLayoutConstraint(item: animationView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 100))
}
you can do it like code below programmatically i hope this help you
import UIKit
class ViewController: UIViewController {
let firstView:UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.blue
return view
}()
let secondView:UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.orange
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
setupViews()
}
func setupViews(){
view.addSubview(firstView)
firstView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: 0).isActive = true
firstView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
firstView.widthAnchor.constraint(equalToConstant: 100).isActive = true
firstView.heightAnchor.constraint(equalToConstant: 100).isActive = true
// second view
firstView.addSubview(secondView)
secondView.centerYAnchor.constraint(equalTo: firstView.centerYAnchor, constant: 0).isActive = true
secondView.centerXAnchor.constraint(equalTo: firstView.centerXAnchor, constant: 0).isActive = true
secondView.widthAnchor.constraint(equalToConstant: 50).isActive = true
secondView.heightAnchor.constraint(equalToConstant: 50).isActive = true
}
}
#IBOutlet weak var viewOn: UIView!
let animationView = LOTAnimationView(name: "restless_gift_ii")
{
animationView.loopAnimation = true
animationView.contentMode = .scaleToFill
animationView.animationSpeed = 1
animationView.backgroundColor = UIColor.black
animationView.frame = viewOn.frame
viewOn.addSubview(animationView)
}
You can try it, hope it's OK
I was having several problems with the alignment and scaling of my Lottie animations. They would show up centered on emulator but not on devices. After debugging for hours, I found out the layout issues were happening because I was setting up the animations on the viewDidLoad(). When I moved the code to viewDidAppear(_ animated: Bool) everything worked like a charm. I hope this may help someone else.

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)
]

programmatic constraints - cover entire superview using layout anchors

Is it possible using layout anchors to cover an entire superview's screen?
Using NSLayoutConstraints, I can achieve this effect using the code below
dimmingView = UIView()
dimmingView.translatesAutoresizingMaskIntoConstraints = false
dimmingView.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
containerView?.addSubview(dimmingView)
NSLayoutConstraint(item: containerView!, attribute: .leadingMargin, relatedBy: .equal, toItem: dimmingView, attribute: .leadingMargin, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: containerView!, attribute: .trailingMargin, relatedBy: .equal, toItem: dimmingView, attribute: .trailingMargin, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: containerView!, attribute: .topMargin, relatedBy: .equal, toItem: dimmingView, attribute: .topMargin, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: containerView!, attribute: .bottomMargin, relatedBy: .equal, toItem: dimmingView, attribute: .bottomMargin, multiplier: 1, constant: 0).isActive = true
I want to switch to layout anchors instead, following what's suggested in the docs. I tried doing this:
let margins = containerView?.layoutMarginsGuide
dimmingView.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
dimmingView.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true
dimmingView.topAnchor.constraint(equalTo: margins.topAnchor).isActive = true
dimmingView.bottomAnchor.constraint(equalTo: margins.bottomAnchor).isActive = true
or this
let margins = containerView?.layoutMarginsGuide
dimmingView.heightAnchor.constraint(equalTo: margins.heightAnchor).isActive = true
dimmingView.widthAnchor.constraint(equalTo: margins.widthAnchor).isActive = true
dimmingView.centerXAnchor.constraint(equalTo: margins.centerXAnchor).isActive = true
dimmingView.centerYAnchor.constraint(equalTo: margins.centerYAnchor).isActive = true
but both did not work. Instead of fully covering containerview, what I end up with are paddings at all 4 sides.
You are constraining to margins and the margins are the space you see. constrain to superview instead:.
dimmingView.heightAnchor.constraint(equalTo: dimmingView.superview!.heightAnchor).isActive = true
dimmingView.widthAnchor.constraint(equalTo: dimmingView.superview!.widthAnchor).isActive = true
dimmingView.centerXAnchor.constraint(equalTo: dimmingView.superview!.centerXAnchor).isActive = true
dimmingView.centerYAnchor.constraint(equalTo: dimmingView.superview!.centerYAnchor).isActive = true
You have to use the attributes .leading, .trailing, .topand .bottom instead of the corresponding .xxxMargin attributes. They will place the subview along the superviews bounds.

Resources