I am creating and pushing a view controller on a button touch using the below code as a utility method attached to the button
func createSmartController() -> UIViewController{
//Create controller and get view
var controller = UIViewController()
var view = controller.view
var tag:String
var count = 0
//Create and layout scroll view
var scrollView = UIScrollView()
scrollView.setTranslatesAutoresizingMaskIntoConstraints(false)
view.addSubview(scrollView)
view.addConstraint(NSLayoutConstraint(item: scrollView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0.0))
view.addConstraint(NSLayoutConstraint(item: scrollView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0.0))
view.addConstraint(NSLayoutConstraint(item: scrollView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0.0))
view.addConstraint(NSLayoutConstraint(item: scrollView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0.0))
//Create and add content view
var scrollContent = UIView()
scrollContent.setTranslatesAutoresizingMaskIntoConstraints(false)
scrollView.addSubview(scrollContent)
scrollView.addConstraint(NSLayoutConstraint(item: scrollContent, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0.0))
scrollView.addConstraint(NSLayoutConstraint(item: scrollContent, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0.0))
scrollView.addConstraint(NSLayoutConstraint(item: scrollContent, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0.0))
scrollView.addConstraint(NSLayoutConstraint(item: scrollContent, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0.0))
view.addConstraint(NSLayoutConstraint(item: scrollContent, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0.0))
view.addConstraint(NSLayoutConstraint(item: scrollContent, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0.0))
//Create all buttons
var buttons = self.GetMyButtons() //Just returns and array of UIButtons
//Add buttons to view with constraints
var prevButton:String
var constH:NSArray
var constV:NSArray
var hString:String
var vString:String
var index = 0
for button in buttons{
button.setTranslatesAutoresizingMaskIntoConstraints(false)
scrollContent.addSubview(button)
button.bounds.size.height = 90
scrollContent.addConstraint(NSLayoutConstraint(item: button, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: scrollContent, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0.0))
scrollContent.addConstraint(NSLayoutConstraint(item: button, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: scrollContent, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0.0))
if(index == 0){
scrollContent.addConstraint(NSLayoutConstraint(item: button, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: scrollContent, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 8.0))
}
else{
scrollContent.addConstraint(NSLayoutConstraint(item: button, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: buttons[index-1], attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 8.0))
}
if(index == buttons.count-1){
scrollContent.addConstraint(NSLayoutConstraint(item: button, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: scrollContent, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: -8.0))
}
index++
}
return controller
}
This method is used in the below call to generate and push the view controller on button touchupinside
var controller = button.getSmartController()
self.navigationController?.pushViewController(controller, animated: true)
However, my view controller that is pushed seems to have no view at all. It is black/blank. The push animation also seems to have a slight hitch.
All background colors were non-existant and showing as black. When programmatically creating elements, the styling must be added as well or all defaults will return as null/black.
Related
I have a box that is initiated without a frame so it has 0 center and size.
let blackBox = UIView()
blackBox.backgroundColor = .blackColor()
blackBox.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(blackBox)
view.addConstraint(NSLayoutConstraint(item: blackBox, attribute: .Width, relatedBy: .Equal, toItem: view, attribute: .Width, multiplier: 0.1, constant: 0))
view.addConstraint(NSLayoutConstraint(item: blackBox, attribute: .Height, relatedBy: .Equal, toItem: view, attribute: .Height, multiplier: 0.5, constant: 0))
view.addConstraint(NSLayoutConstraint(item: blackBox, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: 0))
view.addConstraint(NSLayoutConstraint(item: blackBox, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1, constant: 0))
Is there anyway to insert a centered subview into the blackBox without using autolayout or is there a neater way I could/should use it. The only way I can see this happening is:
let blueBox = UIView()
blackBox.addSubview(blueBox)
blueBox.translatesAutoresizingMaskIntoConstraints = false
blueBox.backgroundColor = UIColor.blueColor()
view.addConstraint(NSLayoutConstraint(item: blueBox, attribute: .CenterX, relatedBy: .Equal, toItem: blackBox, attribute: .CenterX, multiplier: 1, constant: 0))
view.addConstraint(NSLayoutConstraint(item: blueBox, attribute: .CenterY, relatedBy: .Equal, toItem: blackBox, attribute: .CenterY, multiplier: 1, constant: 0))
view.addConstraint(NSLayoutConstraint(item: blueBox, attribute: .Width, relatedBy: .Equal, toItem: blackBox, attribute: .Width, multiplier: 0.4, constant: 0))
view.addConstraint(NSLayoutConstraint(item: blueBox, attribute: .Height, relatedBy: .Equal, toItem: blackBox, attribute: .Height, multiplier: 0.4, constant: 0))
I personally would use var bluebox = UIView(frame: CGRECT) and set the CGRect accordingly.
I created my view as so :
self.scrollView = UIScrollView()
self.scrollView.delegate = self
self.scrollView.contentSize = CGSizeMake(UIScreen.mainScreen().bounds.width, 1000)
containerView = UIView()
containerView.backgroundColor = UIColor.redColor()
scrollView.translatesAutoresizingMaskIntoConstraints = false
containerView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(containerView)
view.addSubview(scrollView)
And then I added these constraints :
// Constraint ScrollView
view.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .Top, relatedBy: .Equal, toItem: view, attribute: .Top, multiplier: 1.0, constant: 0.0))
view.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .Bottom, relatedBy: .Equal, toItem: view, attribute: .Bottom, multiplier: 1.0, constant: 0.0))
view.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .Leading, relatedBy: .Equal, toItem: view, attribute: .Leading, multiplier: 1.0, constant: 0.0))
view.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .Trailing, relatedBy: .Equal, toItem: view, attribute: .Trailing, multiplier: 1.0, constant: 0.0))
// Constraint ContainerView
scrollView.addConstraint(NSLayoutConstraint(item: containerView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0.0))
scrollView.addConstraint(NSLayoutConstraint(item: containerView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0.0))
scrollView.addConstraint(NSLayoutConstraint(item: containerView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0.0))
scrollView.addConstraint(NSLayoutConstraint(item: containerView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0.0))
And this :
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
scrollView.frame = view.bounds
containerView.frame = CGRectMake(0, 0, scrollView.contentSize.width, scrollView.contentSize.height)
}
But when I change the orientation, the width of the containerView remains the same. How can I ensure that the width expands to the width of the scrollView to it's new layout?
You should replace
scrollView.addConstraint(NSLayoutConstraint(item: containerView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0.0))
scrollView.addConstraint(NSLayoutConstraint(item: containerView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0.0))
with
view.addConstraint(NSLayoutConstraint(item: containerView, attribute: .Height, relatedBy: .Equal, toItem: scrollView, attribute: .Height, multiplier: 1.0, constant: 0.0))
view.addConstraint(NSLayoutConstraint(item: containerView, attribute: .Width, relatedBy: .Equal, toItem: scrollView, attribute: .Width, multiplier: 1.0, constant: 0.0))
This uses the width and height of the scroll view instead of stretching the container view to the right side and bottom of the scroll view. It seems to work much better. I also added the constraint to a common ancestor, as per the docs but it also works by adding to scrollView, so take your choice whether you want to add all constraints to the view instead of the scrollView or not.
Further note
In iOS 8 and later you can simply activate your constraints instead of adding them to your view.
NSLayoutConstraint(item: containerView, attribute: .Top, relatedBy: .Equal, toItem: scrollView, attribute: .Top, multiplier: 1.0, constant: 0.0).active = true
In iOS 9, which I like even more you can use anchors, e.g.
scrollView.topAnchor.constraintEqualToAnchor(topLayoutGuide.bottomAnchor).active = true
You don't need to do anything in layoutSubviews. The translatesAutoresizingMaskIntoConstraints property should indeed be set to false NOT true.
you should also add these constraints
containerView.addConstraint(NSLayoutConstraint(item: containerView, attribute: .Top, relatedBy: .Equal, toItem: scrollView, attribute: .Top, multiplier: 1.0, constant: 0.0))
containerView.addConstraint(NSLayoutConstraint(item: containerView, attribute: .Bottom, relatedBy: .Equal, toItem: scrollView, attribute: .Bottom, multiplier: 1.0, constant: 0.0))
containerView.addConstraint(NSLayoutConstraint(item: containerView, attribute: .Leading, relatedBy: .Equal, toItem: scrollView, attribute: .Leading, multiplier: 1.0, constant: 0.0))
containerView.addConstraint(NSLayoutConstraint(item: containerView, attribute: .Trailing, relatedBy: .Equal, toItem: scrollView, attribute: .Trailing, multiplier: 1.0, constant: 0.0))
I have an uiview with two uibuttons.
The issue is - i cannot understand how to use auto-layout constraints in order to position them the following way
Thank you in advance for any insights!
Try something like this:
//Individual button Width
self.view.addConstraint(NSLayoutConstraint(item: button1, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Width, multiplier: 0.25, constant: 0))
self.view.addConstraint(NSLayoutConstraint(item: button2, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Width, multiplier: 0.25, constant: 0))
//Button1 left spacing
self.view.addConstraint(NSLayoutConstraint(item: button1, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: self.view.frame.size.width * 0.15))
//Button2 Right Spacing
self.view.addConstraint(NSLayoutConstraint(item: button2, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: -self.view.frame.size.width * 0.15))
//Y placement
self.view.addConstraint(NSLayoutConstraint(item: button1, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0))
self.view.addConstraint(NSLayoutConstraint(item: button1, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: button2, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0))
Also, you will need to reset the constraints on rotation as self.view.frame.size.width will change. It has been used to calculate the constraint constants.
If you don't want to reset the constraints you can try to make the spacing constraints like this:
self.view.addConstraint(NSLayoutConstraint(item: self.view, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: button1, attribute: NSLayoutAttribute.CenterX, multiplier: 0.275, constant: 0))
self.view.addConstraint(NSLayoutConstraint(item: self.view, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: button2, attribute: NSLayoutAttribute.CenterX, multiplier: 0.625, constant: 0))
Note that the order of views is reversed.
I've used it successfully with IB, should work from code.
For the life of me I can't figure out what I'm doing wrong. All I'm trying to do is put a bunch of text fields in a scroll view and have it intrinsically determine the contentSize using auto layout. Unlike the other tutorials I've watched and read out there, I'm trying to do this programmatically, not through Storyboards or Xibs.
I've called setTranslatesAutoresizingMaskIntoConstraints(false) on every view in the scroll view (including on the scroll view itself).
I've set the height and width of the scroll view to match it's superview and even positioned the scroll view in the center of it's superview (I read that sometimes you need to do that to get it working)
I've pinned the content view's edges to the top, leading, trailing, and bottom edges of it's superview (the scroll view)
Here's my code:
class ViewController: UIViewController {
var scrollView = UIScrollView()
var contentView = UIView()
var textField1 = CustomTextField()
var textField2 = CustomTextField()
var textField3 = CustomTextField()
var textField4 = CustomTextField()
var textField5 = CustomTextField()
var textField6 = CustomTextField()
override func viewDidLoad() {
super.viewDidLoad()
scrollView.setTranslatesAutoresizingMaskIntoConstraints(false)
contentView.setTranslatesAutoresizingMaskIntoConstraints(false)
textField1.setTranslatesAutoresizingMaskIntoConstraints(false)
textField2.setTranslatesAutoresizingMaskIntoConstraints(false)
textField3.setTranslatesAutoresizingMaskIntoConstraints(false)
textField4.setTranslatesAutoresizingMaskIntoConstraints(false)
textField5.setTranslatesAutoresizingMaskIntoConstraints(false)
textField6.setTranslatesAutoresizingMaskIntoConstraints(false)
view.addSubview(scrollView)
scrollView.addSubview(contentView)
contentView.addSubview(textField1)
contentView.addSubview(textField2)
contentView.addSubview(textField3)
contentView.addSubview(textField4)
contentView.addSubview(textField5)
contentView.addSubview(textField6)
contentView.backgroundColor = .redColor()
setupConstraints()
}
func setupConstraints() {
// Install height and width constraints on our scroll view
let heightLC : NSLayoutConstraint = NSLayoutConstraint(item: scrollView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Height, multiplier: 1.0, constant: 0)
let widthLC : NSLayoutConstraint = NSLayoutConstraint(item: scrollView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Width, multiplier: 1.0, constant: 0)
self.view.addConstraints([heightLC,widthLC])
// Install centering constraints on our scroll view
let centerXLC : NSLayoutConstraint = NSLayoutConstraint(item: scrollView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterX, multiplier: 1.0, constant: 0)
let centerYLC : NSLayoutConstraint = NSLayoutConstraint(item: scrollView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant: 0)
self.view.addConstraints([centerXLC,centerYLC])
// Set the content view so it resizes with the same proportions on screen rotations //
let contentViewTopLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0)
let contentViewLeadingLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0)
let contentViewTrailingLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0)
let contentViewBottomLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0)
let contentViewWidthLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Width, multiplier: 1.0, constant: 0)
let contentViewHeightLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Height, multiplier: 1.0, constant: 0)
scrollView.addConstraints([contentViewTopLC,contentViewLeadingLC,contentViewTrailingLC,contentViewBottomLC,contentViewWidthLC,contentViewHeightLC])
// Setup the text field constraints
let textField1Top : NSLayoutConstraint = NSLayoutConstraint(item: textField1, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0)
let textField1Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField1, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
let textField1Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField1, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
contentView.addConstraints([textField1Top, textField1Leading, textField1Trailing])
let textField2Top : NSLayoutConstraint = NSLayoutConstraint(item: textField2, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: textField1, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 100)
let textField2Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField2, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
let textField2Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField2, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
contentView.addConstraints([textField2Top, textField2Leading, textField2Trailing])
let textField3Top : NSLayoutConstraint = NSLayoutConstraint(item: textField3, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: textField2, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 100)
let textField3Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField3, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
let textField3Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField3, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
contentView.addConstraints([textField3Top, textField3Leading, textField3Trailing])
let textField4Top : NSLayoutConstraint = NSLayoutConstraint(item: textField4, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: textField3, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 100)
let textField4Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField4, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
let textField4Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField4, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
contentView.addConstraints([textField4Top, textField4Leading, textField4Trailing])
let textField5Top : NSLayoutConstraint = NSLayoutConstraint(item: textField5, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: textField4, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 100)
let textField5Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField5, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
let textField5Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField5, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
contentView.addConstraints([textField5Top, textField5Leading, textField5Trailing])
let textField6Top : NSLayoutConstraint = NSLayoutConstraint(item: textField6, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: textField5, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 100)
let textField6Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField6, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
let textField6Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField6, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
let textField6Bottom : NSLayoutConstraint = NSLayoutConstraint(item: textField6, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.GreaterThanOrEqual, toItem: contentView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0)
contentView.addConstraints([textField6Top, textField6Leading, textField6Trailing, textField6Bottom])
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
And here's my CustomTextField class I use for the text fields:
class CustomTextField: UITextField {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .whiteColor()
// set text field height to 55pts
let heightLC : NSLayoutConstraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 55)
addConstraint(heightLC)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Here's what the app currently looks like
(notice the 6th text field isn't being displayed and I can't scroll down to it):
Any help will greatly be appreciated :)
The problem is these lines:
let contentViewTopLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0)
let contentViewLeadingLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0)
let contentViewTrailingLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0)
let contentViewBottomLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0)
let contentViewWidthLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Width, multiplier: 1.0, constant: 0)
let contentViewHeightLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Height, multiplier: 1.0, constant: 0)
scrollView.addConstraints([contentViewTopLC,contentViewLeadingLC,contentViewTrailingLC,contentViewBottomLC,contentViewWidthLC,contentViewHeightLC])
What you want is not for the content view to be sized like the scroll view at all. That is exactly what is keeping the scroll view from scrolling. You want the content view's four edges to be pinned to the four edges of the scroll view.
That way, the contents of the content view will push outwards on the content view, sizing it. It will thus try to become bigger than the scroll view. But it can't, because you're also going to pin the sides of the scroll view to its superview. Thus, the content view's size will become the bounds size of the scroll view - its contentSize. When the contentSize of the scroll view is thus bigger than the scroll view, it will be scrollable.
I am working with a series of 4 buttons. All same width and height that combined stretch the width of the view. I have tried visually constraining them to each other and to a label (also the width of the view) above them. I used the Leading edge to view constraint on my far left button and trailing edge to view constraint on my far right button. I also used horizontal space constraints (which should be zero) on all of my buttons. despite this when I run my simulator the third button over is always over lapping with the fourth to some degree. I've gone through and deleted all the constraints and tried adding them again and the same over lap happened. Is there something I am missing/doing wrong? Why wont my all buttons shrink to fit the view instead of overlapping?
I have something similar in my code, if u are setting button constraints programatically, i have a scrollview and a contentview inside it and setted constraints in storyboard, but other stuff i add programatically
button1.setTranslatesAutoresizingMaskIntoConstraints(false)
constX = NSLayoutConstraint(item: button1, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: ContentView, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0)
view.addConstraint(constX)
constTop = NSLayoutConstraint(item: button1, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: ContentView, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 20)
view.addConstraint(constTop)
constL = NSLayoutConstraint(item: button1, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: ContentView, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 20)
view.addConstraint(constL)
constR = NSLayoutConstraint(item: button1, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: ContentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: -20)
view.addConstraint(constR)
constH = NSLayoutConstraint(item: button1, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 50)
button1.addConstraint(constH)
button2.setTranslatesAutoresizingMaskIntoConstraints(false)
constX = NSLayoutConstraint(item: button2, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: ContentView, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0)
view.addConstraint(constX)
constTop = NSLayoutConstraint(item: button2, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: button1, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 10)
view.addConstraint(constTop)
constL = NSLayoutConstraint(item: button2, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: ContentView, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 20)
view.addConstraint(constL)
constR = NSLayoutConstraint(item: button2, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: ContentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: -20)
view.addConstraint(constR)
constH = NSLayoutConstraint(item: button2, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 50)
button2.addConstraint(constH)
button3.setTranslatesAutoresizingMaskIntoConstraints(false)
constX = NSLayoutConstraint(item: button3, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: ContentView, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0)
view.addConstraint(constX)
constL = NSLayoutConstraint(item: button3, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: ContentView, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 20)
view.addConstraint(constL)
constR = NSLayoutConstraint(item: button3, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: ContentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: -20)
view.addConstraint(constR)
constTop = NSLayoutConstraint(item: button3, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: button2, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 20)
view.addConstraint(constTop)
constH = NSLayoutConstraint(item: button3, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 50)
button3.addConstraint(constH)
button4.setTranslatesAutoresizingMaskIntoConstraints(false)
constX = NSLayoutConstraint(item: button4, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: ContentView, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0)
view.addConstraint(constX)
constTop = NSLayoutConstraint(item: button4, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: button3, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 10)
view.addConstraint(constTop)
var constBottom = NSLayoutConstraint(item: button4, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: ContentView, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: -20)
view.addConstraint(constBottom)
constL = NSLayoutConstraint(item: button4, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: ContentView, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 20)
view.addConstraint(constL)
constR = NSLayoutConstraint(item: button4, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: ContentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: -20)
view.addConstraint(constR)
constH = NSLayoutConstraint(item: button4, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant:50)
button4.addConstraint(constH)
So there are 4 buttons, constrained to themselves and button1.top to Contentview.Top and button4.Bottom to ContentView.Bottom