Using auto layout at the expense of having no frame - ios

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.

Related

UITextView and UIImageView in ScrollView

I want to make editable-textview and imageview both scroll. (Like Vesper app!) I have to do this programmatically.
I followed this post uitextview-inside-uiscrollview-with-autolayout
And I made this in code, but it doesn't scroll!
noteTextView.isScrollEnabled = false
//Adding views
view.addSubview(bScrollView)
bScrollView.addSubview(nView)
nView.addSubview(photoImageView)
nView.addSubview(noteTextView)
//The scrollview constraint
let Sleft = NSLayoutConstraint(item: bScrollView, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.leading, multiplier: 1, constant: 0)
let Sright = NSLayoutConstraint(item: view, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: bScrollView, attribute: NSLayoutAttribute.trailing, multiplier: 1, constant: 0)
let Sbottom = NSLayoutConstraint(item: bottomLayoutGuide, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: bScrollView, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0)
let Stop = NSLayoutConstraint(item: bScrollView, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0)
//The view constraint
let Vleft = NSLayoutConstraint(item: nView, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.leading, multiplier: 1, constant: 0)
let Vright = NSLayoutConstraint(item: view, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: nView, attribute: NSLayoutAttribute.trailing, multiplier: 1, constant: 0)
let Vbottom = NSLayoutConstraint(item: view, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: nView, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0)
let Vtop = NSLayoutConstraint(item: nView, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0)
let Vequal = NSLayoutConstraint(item: nView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.width, multiplier: 1, constant: 0)
//The textview constraint
let Nleft = NSLayoutConstraint(item: noteTextView, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: nView, attribute: NSLayoutAttribute.leading, multiplier: 1, constant: 0)
let Nright = NSLayoutConstraint(item: nView, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: noteTextView, attribute: NSLayoutAttribute.trailing, multiplier: 1, constant: 0)
let Nbottom = NSLayoutConstraint(item: nView, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: noteTextView, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0)
let Ntop = NSLayoutConstraint(item: noteTextView, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: photoImageView, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0)
let Nheight = NSLayoutConstraint(item: noteTextView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.greaterThanOrEqual, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 268)
//The imageview constraint
let Pleft = NSLayoutConstraint(item: photoImageView, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: nView, attribute: NSLayoutAttribute.leading, multiplier: 1, constant: 0)
let Pright = NSLayoutConstraint(item: nView, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: photoImageView, attribute: NSLayoutAttribute.trailing, multiplier: 1, constant: 0)
let Ptop = NSLayoutConstraint(item: photoImageView, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: nView, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0)
let Pheight = NSLayoutConstraint(item: photoImageView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 300)
NSLayoutConstraint.activate([
Sleft, Sright, Sbottom, Stop,
Vleft, Vright, Vbottom, Vtop, Vequal,
Nleft, Nright, Nbottom, Ntop, Nheight,
Pleft, Pright, Ptop, Pheight
])
How can I make textView and imageView like Vesper app? Is there are another way?
You're code has some issues, try this:
class ViewController: UIViewController {
var bScrollView:UIScrollView!
var nView:UIView!
var photoImageView:UIImageView!
var noteTextView:UITextView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.translatesAutoresizingMaskIntoConstraints = false
bScrollView = UIScrollView.init(frame: CGRect.init(x: 0, y: 0, width: 50, height: 50))
bScrollView.backgroundColor = UIColor.black
nView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: 50, height: 50))
nView.backgroundColor = UIColor.blue
photoImageView = UIImageView.init(frame: CGRect.init(x: 0, y: 0, width: 50, height: 50))
photoImageView.backgroundColor = UIColor.red
noteTextView = UITextView.init(frame: CGRect.init(x: 0, y: 0, width: 50, height: 50))
noteTextView.backgroundColor = UIColor.yellow
noteTextView.clipsToBounds = true
bScrollView.translatesAutoresizingMaskIntoConstraints = false
nView.translatesAutoresizingMaskIntoConstraints = false
photoImageView.translatesAutoresizingMaskIntoConstraints = false
noteTextView.translatesAutoresizingMaskIntoConstraints = false
noteTextView.isScrollEnabled = false
//Adding views
view.addSubview(bScrollView)
bScrollView.addSubview(nView)
nView.addSubview(photoImageView)
nView.addSubview(noteTextView)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
//The scrollview constraint
let sLeading = NSLayoutConstraint(item: bScrollView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1, constant: 0)
let sTrailing = NSLayoutConstraint(item: bScrollView, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: 0)
let sTop = NSLayoutConstraint(item: bScrollView, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1, constant: 0)
let sBottom = NSLayoutConstraint(item: bScrollView, attribute: .bottom, relatedBy: .equal, toItem: bottomLayoutGuide, attribute: .bottom , multiplier: 1, constant: 0)
view.addConstraints([sLeading, sTrailing, sTop, sBottom])
//The view constraint
let vLeading = NSLayoutConstraint(item: nView, attribute: .leading, relatedBy: .equal, toItem: bScrollView, attribute: .leading, multiplier: 1, constant: 0)
let vTrailing = NSLayoutConstraint(item: nView, attribute: .trailing, relatedBy: .equal, toItem: bScrollView, attribute: .trailing, multiplier: 1, constant: 0)
let vTop = NSLayoutConstraint(item: nView, attribute: .top, relatedBy: .equal, toItem: bScrollView, attribute: .top, multiplier: 1, constant: 0)
let vBottom = NSLayoutConstraint(item: nView, attribute: .bottom, relatedBy: .equal, toItem: bScrollView, attribute: .bottom, multiplier: 1, constant: 0)
bScrollView.addConstraints([vLeading, vTrailing, vTop, vBottom])
let hEqual = NSLayoutConstraint(item: nView, attribute: .height, relatedBy: .equal, toItem: view, attribute: .height, multiplier: 1, constant: 0)
let wEqual = NSLayoutConstraint(item: nView, attribute: .width, relatedBy: .equal, toItem: view, attribute: .width, multiplier: 1, constant: 0)
view.addConstraints([hEqual, wEqual])
//The imageview constraint
let pLeading = NSLayoutConstraint(item: photoImageView, attribute: .leading, relatedBy: .equal, toItem: nView, attribute: .leading, multiplier: 1, constant: 0)
let pTrailing = NSLayoutConstraint(item: photoImageView, attribute: .trailing, relatedBy: .equal, toItem: nView, attribute: .trailing, multiplier: 1, constant: 0)
let pTop = NSLayoutConstraint(item: photoImageView, attribute: .top, relatedBy: .equal, toItem: nView, attribute: .top, multiplier: 1, constant: 0)
let pHeight = NSLayoutConstraint(item: photoImageView, attribute: .height, relatedBy: .equal, toItem: nView, attribute: .width, multiplier: 1.0, constant: 0)
nView.addConstraints([pLeading, pTrailing, pTop, pHeight])
//The textview constraint
let txtLeading = NSLayoutConstraint(item: noteTextView, attribute: .leading, relatedBy: .equal, toItem: nView, attribute: .leading, multiplier: 1, constant: 0)
let txtTrailing = NSLayoutConstraint(item: noteTextView, attribute: .trailing, relatedBy: .equal, toItem: nView, attribute: .trailing, multiplier: 1, constant: 0)
let txtTop = NSLayoutConstraint(item: noteTextView, attribute: .top, relatedBy: .equal, toItem: photoImageView, attribute: .bottom, multiplier: 1, constant: 0)
let txtBottom = NSLayoutConstraint(item: noteTextView, attribute: .bottom, relatedBy: .equal, toItem: nView, attribute: .bottom, multiplier: 1.0, constant: 0)
nView.addConstraints([txtTop, txtLeading, txtTrailing, txtBottom])
view.layoutIfNeeded()
}
}

Xcode adds duplicate constraints?

In code I added 4 constraints. But when I run the app, in UI debugger, it shows additional 6 constraints? It should be all clear with these 4 I added. I don't know what I'm doing wrong?
let leftConstr = NSLayoutConstraint(item: image, attribute: .leading, relatedBy: .equal, toItem: cell.contentView, attribute: .leading, multiplier: 1.0, constant: 0.0)
let bottomConstr = NSLayoutConstraint(item: image, attribute: .bottom, relatedBy: .equal, toItem: cell.contentView , attribute: .bottom, multiplier: 1.0, constant: 0.0)
let highthConstr = NSLayoutConstraint(item: image, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 15)
let widthConstr = NSLayoutConstraint(item: image, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 50)
cell.contentView.addConstraints([highthConstr, widthConstr, bottomConstr, leftConstr])
Here is the screenshot of my UI debugger
Maybe you can try to add this line of code before :
image.translatesAutoresizingMaskIntoConstraints = false

View hierarchy is not prepared for the constraint: Unable to Find the Issue

The Following are the constraints that am using.
<NSLayoutConstraint:0x7fcfdd405bc0 UILabel:0x7fcfdd405780'ACTIVITY'.centerY == UIView:0x7fcfdb677b60.centerY>The view hierarchy is not prepared for the constraint:
footer!.frame = CGRectMake(0, 0, tableView.frame.size.width, FOOTER_HEIGHT)
let activityLabel = UILabel()
activityLabel.text = "SomeText"
activityLabel.translatesAutoresizingMaskIntoConstraints = false
let CenterConstraint = NSLayoutConstraint(item: activityLabel, attribute: .CenterX, relatedBy: .Equal, toItem: footerView, attribute: .CenterX, multiplier: 1, constant: 0)
let CenterConstraint = NSLayoutConstraint(item: activityLabel, attribute: .CenterY, relatedBy: .Equal, toItem: footerView, attribute: .CenterY, multiplier: 1, constant: 0)
footer!.addConstraints([xxCenterConstraint,yyCenterConstraint])
footer!.addSubview(activityLabel)
let notificationLabel = UILabel()
notificationLabel.text = "9"
notificationLabel.textAlignment = .Center
notificationLabel.backgroundColor = customBlueColor
footerView!.addSubview(notificationLabel)
notificationLabel.translatesAutoresizingMaskIntoConstraints = false
let width = NSLayoutConstraint(item: notificationLabel, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: NOTIFICATION_LABEL_HEIGHT)
let height = NSLayoutConstraint(item: notificationLabel, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: NOTIFICATION_LABEL_HEIGHT)
let yCenterConstraint = NSLayoutConstraint(item: notificationLabel, attribute: .CenterY, relatedBy: .Equal, toItem: footerView, attribute: .CenterY, multiplier: 1, constant: 0)
let leadingConstraint1 = NSLayoutConstraint(item: activityLabel, attribute: .Trailing, relatedBy: .Equal, toItem: notificationLabel, attribute: .Leading, multiplier: 1, constant:-LEADING_SPACE)
footer!.addConstraints([width,height,yCenterConstraint,leadingConstraint1])
notificationLabel.layer.cornerRadius = NOTIFICATION_LABEL_HEIGHT/2
notificationLabel.clipsToBounds = true
You can't add constraints before the views are part of the same view hierarchy. Move the addSubview line before the addConstraints line.

Constraints are not expanding my View on orientation change

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

Swift NSlayoutConstraint

I have a question... I am really not understand something.
I have a UIView Class which only create a UITextLabel.. I'm trying to add instances from this class to my Viewcontroller. This is how my UIViewClass look like:
class PostLineItem: UIView {
var labelText : String!
var labelHeader : String!
init(labelText: String , labelHeader: String) {
super.init(frame: CGRect.zeroRect)
self.labelText = labelText
self.labelHeader = labelHeader
let tlb = timeLineBlock()
//tlb.setTranslatesAutoresizingMaskIntoConstraints(false)
self.addSubview(tlb)
NSLayoutConstraint.activateConstraints([
NSLayoutConstraint(item: tlb, attribute: .Height, relatedBy: .Equal, toItem: self, attribute: .Height, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: tlb, attribute: .Width, relatedBy: .Equal, toItem: self, attribute: .Width, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: tlb, attribute: .Left, relatedBy: .Equal, toItem: self, attribute: .Left, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: tlb, attribute: .Top, relatedBy: .Equal, toItem: self, attribute: .Top, multiplier: 1.0, constant: 0)
])
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
println("required public")
}
private func timeLineBlock() -> UIView{
let viewNew = UIView()
viewNew.setTranslatesAutoresizingMaskIntoConstraints(false)
let titleLabel = UILabel()
titleLabel.setTranslatesAutoresizingMaskIntoConstraints(false)
titleLabel.font = UIFont(name: "ArialMT", size: 20)
titleLabel.textColor = UIColor.blackColor()
titleLabel.text = labelHeader
titleLabel.numberOfLines = 0
viewNew.addSubview(titleLabel)
titleLabel.backgroundColor = UIColor.redColor()
/* IF I NOT COMMENT THIS PART INSTANCE OF THIS CLASS IS NOT SHOWING UP.
viewNew.addConstraints([
NSLayoutConstraint(item: titleLabel, attribute: .Width, relatedBy: .Equal, toItem: viewNew, attribute: .Width, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: titleLabel, attribute: .Left, relatedBy: .Equal, toItem: viewNew, attribute: .Left, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: titleLabel, attribute: .Top, relatedBy: .Equal, toItem: viewNew, attribute: .Top, multiplier: 1.0, constant: 0)
])
*/
viewNew.backgroundColor = UIColor.greenColor()
return viewNew
}
}
And this is my viewController class part where i try to instantiate the PostLineItem instances..
let guideView = UIView()
guideView.setTranslatesAutoresizingMaskIntoConstraints(false)
guideView.backgroundColor = UIColor.blackColor()
scrollView.addSubview(guideView)
scrollView.addConstraints([
NSLayoutConstraint(item: guideView, attribute: .Top, relatedBy: .Equal, toItem: scrollView, attribute: .Top, multiplier: 1.0, constant: 50),
NSLayoutConstraint(item: guideView, attribute: .Left, relatedBy: .Equal, toItem: scrollView, attribute: .Left, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: guideView, attribute: .Width, relatedBy: .Equal, toItem: scrollView, attribute: .Width, multiplier: 1.0, constant: -30),
NSLayoutConstraint(item: guideView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant:10)
])
guideView.backgroundColor = UIColor.blackColor()
var viewFromAbove = guideView
for post in 1...70 {
let v = PostLineItem(labelText: "Tst", labelHeader: "Tst2")
scrollView.addSubview(v)
NSLayoutConstraint.activateConstraints([
NSLayoutConstraint(item: v, attribute: .Top, relatedBy: .Equal, toItem: viewFromAbove, attribute: .Bottom, multiplier: 1.0, constant: 15),
NSLayoutConstraint(item: v, attribute: .Left, relatedBy: .Equal, toItem: viewFromAbove, attribute: .Left, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: v, attribute: .Width, relatedBy: .Equal, toItem: viewFromAbove, attribute: .Width, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: v, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 400)
])
viewFromAbove = v
}
scrollView.addConstraints([
NSLayoutConstraint(item: viewFromAbove, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: -10)
])
As you can see, first of all i create a guidview for the first PostLineItem and then adding the new instances and the constraints.. So..
If i do it this way the instances of the PostLineItem class will be at the same places and hides each others... I think, the NSLAyoutConstaint not effect.
But, as you can see at the commented part of the code, if i create a simple UILabel the constraints work fine, and all of the UILabel instances will be under each others..
UPDATE:
after i adding all of written in the answer it's look like this.. :(
That little red rect is my PostLineItem instance.. :(
UPDATED - all code.
I'm thinking you might be adding the constraints to the wrong views. For instance, the guideView height constraint should be added to the guideView, and not the scrollView. I would suggest instead you use the new way of activating constraints. Instead of adding them to the views, you just call the activateConstraints class method on NSLayoutConstraint:
NSLayoutConstraint.activateConstraints([
NSLayoutConstraint(item: guideView, attribute: .Top, relatedBy: .Equal, toItem: scrollView, attribute: .Top, multiplier: 1.0, constant: 24),
NSLayoutConstraint(item: guideView, attribute: .Left, relatedBy: .Equal, toItem: scrollView, attribute: .Left, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: guideView, attribute: .Width, relatedBy: .Equal, toItem: scrollView, attribute: .Width, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: guideView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant:4)
])
and
NSLayoutConstraints.activateConstraints([
NSLayoutConstraint(item: v, attribute: .Top, relatedBy: .Equal, toItem: viewFromAbove, attribute: .Bottom, multiplier: 1.0, constant: 5),
NSLayoutConstraint(item: v, attribute: .Left, relatedBy: .Equal, toItem: viewFromAbove, attribute: .Left, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: v, attribute: .Width, relatedBy: .Equal, toItem: viewFromAbove, attribute: .Width, multiplier: 1.0, constant: 0),
])
Also, you are missing a constraint for the height of your PostLineItem, something like:
NSLayoutConstraint(item: v, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant:10)
In your PostLineItem init, you need to add constraints for the timeLineBlock:
init(labelText: String , labelHeader: String) {
super.init(frame: CGRect.zeroRect)
self.labelText = labelText
self.labelHeader = labelHeader
let tlb = timeLineBlock()
self.addSubview(tlb)
NSLayoutConstraint.activateConstraints([
NSLayoutConstraint(item: tlb, attribute: .Height, relatedBy: .Equal, toItem: self, attribute: .Height, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: tlb, attribute: .Width, relatedBy: .Equal, toItem: self, attribute: .Width, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: tlb, attribute: .Left, relatedBy: .Equal, toItem: self, attribute: .Left, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: tlb, attribute: .Top, relatedBy: .Equal, toItem: self, attribute: .Top, multiplier: 1.0, constant: 0)
])
}
Here is my version. I'm getting much better results. Take a look... Note, I set up my scrollView entirely in Interface Builder and just added an outlet called scrollView that points to the contentView contained by my scrollView. That shouldn't matter. Everything else is as you implemented.
class PostLineItem: UIView {
var labelText : String!
var labelHeader : String!
init(labelText: String , labelHeader: String) {
super.init(frame: CGRect.zeroRect)
self.labelText = labelText
self.labelHeader = labelHeader
let tlb = timeLineBlock()
self.addSubview(tlb)
NSLayoutConstraint.activateConstraints([
NSLayoutConstraint(item: tlb, attribute: .Height, relatedBy: .Equal, toItem: self, attribute: .Height, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: tlb, attribute: .Width, relatedBy: .Equal, toItem: self, attribute: .Width, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: tlb, attribute: .Left, relatedBy: .Equal, toItem: self, attribute: .Left, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: tlb, attribute: .Top, relatedBy: .Equal, toItem: self, attribute: .Top, multiplier: 1.0, constant: 0)
])
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
println("required public")
}
private func timeLineBlock() -> UIView{
let viewNew = UIView()
viewNew.setTranslatesAutoresizingMaskIntoConstraints(false)
let titleLabel = UILabel()
titleLabel.setTranslatesAutoresizingMaskIntoConstraints(false)
titleLabel.font = UIFont(name: "ArialMT", size: 20)
titleLabel.textColor = UIColor.blackColor()
titleLabel.text = labelHeader
titleLabel.numberOfLines = 0
viewNew.addSubview(titleLabel)
titleLabel.backgroundColor = UIColor.redColor()
NSLayoutConstraint.activateConstraints([
NSLayoutConstraint(item: titleLabel, attribute: .Width, relatedBy: .Equal, toItem: viewNew, attribute: .Width, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: titleLabel, attribute: .Left, relatedBy: .Equal, toItem: viewNew, attribute: .Left, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: titleLabel, attribute: .Top, relatedBy: .Equal, toItem: viewNew, attribute: .Top, multiplier: 1.0, constant: 0)
])
viewNew.backgroundColor = UIColor.greenColor()
return viewNew
}
}
class ViewController: UIViewController {
#IBOutlet weak var scrollView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let guideView = UIView()
guideView.setTranslatesAutoresizingMaskIntoConstraints(false)
guideView.backgroundColor = UIColor.blackColor()
scrollView.addSubview(guideView)
NSLayoutConstraint.activateConstraints([
NSLayoutConstraint(item: guideView, attribute: .Top, relatedBy: .Equal, toItem: scrollView, attribute: .Top, multiplier: 1.0, constant: 24),
NSLayoutConstraint(item: guideView, attribute: .Left, relatedBy: .Equal, toItem: scrollView, attribute: .Left, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: guideView, attribute: .Width, relatedBy: .Equal, toItem: scrollView, attribute: .Width, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: guideView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant:4)
])
guideView.backgroundColor = UIColor.blackColor()
var viewFromAbove = guideView
for post in 1...70 {
let v = PostLineItem(labelText: "Tst", labelHeader: "Tst2")
//let v = UILabel(frame: CGRectMake(0, 0, 10, 10))
//v.text = "Tst Now with this its working, and the constraint is fine."
v.setTranslatesAutoresizingMaskIntoConstraints(false)
scrollView.addSubview(v)
NSLayoutConstraint.activateConstraints([
NSLayoutConstraint(item: v, attribute: .Top, relatedBy: .Equal, toItem: viewFromAbove, attribute: .Bottom, multiplier: 1.0, constant: 5),
NSLayoutConstraint(item: v, attribute: .Left, relatedBy: .Equal, toItem: viewFromAbove, attribute: .Left, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: v, attribute: .Width, relatedBy: .Equal, toItem: viewFromAbove, attribute: .Width, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: v, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant:30)
])
viewFromAbove = v
}
}
}

Resources