Layout Constraints Added Programmatically to UITableViewCell - ios

I am attempting to reproduce the constraints in this screenshot, which are applied to a static UITableViewCell:
Here is the code I'm using to try to do this:
#IBOutlet weak var cellTest: UITableViewCell!
override func viewDidLoad() {
super.viewDidLoad()
cellTest.backgroundColor = UIColor.yellowColor()
let vw = UIView()
vw.backgroundColor = UIColor.greenColor()
cellTest.contentView.addSubview(vw)
cellTest.contentView.translatesAutoresizingMaskIntoConstraints = false
vw.translatesAutoresizingMaskIntoConstraints = false
let constraintWidth = NSLayoutConstraint(item: vw, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 400)
let constraintHeight = NSLayoutConstraint(item: vw, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 150)
let constraintCentreX = NSLayoutConstraint(item: vw, attribute: .CenterX, relatedBy: .Equal, toItem: vw.superview!, attribute: .CenterX, multiplier: 1, constant: 0)
let constraintCentreY = NSLayoutConstraint(item: vw, attribute: .CenterY, relatedBy: .Equal, toItem: vw.superview!, attribute: .CenterY, multiplier: 1, constant: 0)
cellTest.contentView.addConstraints([constraintWidth, constraintHeight, constraintCentreX, constraintCentreY ])
}
However, below is the unexpected output, with the view in the top left instead of centred. Any help is much appreciated as I've spent quite some time trying to figure this out:

I needed to add constraints to the cell's contentView, as well. These are added to the cell itself.
Code and screenshot below.
#IBOutlet weak var cellTest: UITableViewCell!
override func viewDidLoad() {
super.viewDidLoad()
cellTest.backgroundColor = UIColor.yellowColor()
let vw = UIView()
vw.backgroundColor = UIColor.greenColor()
cellTest.contentView.addSubview(vw)
cellTest.contentView.translatesAutoresizingMaskIntoConstraints = false
vw.translatesAutoresizingMaskIntoConstraints = false
let bottomConstraint = NSLayoutConstraint(item: cellTest.contentView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: cellTest.contentView.superview!, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)
let trailingConstraint = NSLayoutConstraint(item: cellTest.contentView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: cellTest.contentView.superview!, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: 0)
let topConstraint = NSLayoutConstraint(item: cellTest.contentView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: cellTest.contentView.superview!, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0)
let leadingConstraint = NSLayoutConstraint(item: cellTest.contentView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: cellTest.contentView.superview!, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 0)
cellTest.addConstraints([bottomConstraint, trailingConstraint, topConstraint, leadingConstraint])
let constraintWidth = NSLayoutConstraint(item: vw, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 200)
constraintWidth.priority = 1000
let constraintHeight = NSLayoutConstraint(item: vw, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 80)
constraintHeight.priority = 1000
let constraintCentreX = NSLayoutConstraint(item: vw, attribute: .CenterX, relatedBy: .Equal, toItem: vw.superview!, attribute: .CenterX, multiplier: 1, constant: 0)
constraintCentreX.priority = 1000
let constraintCentreY = NSLayoutConstraint(item: vw, attribute: .CenterY, relatedBy: .Equal, toItem: vw.superview!, attribute: .CenterY, multiplier: 1, constant: 0)
constraintCentreY.priority = 1000
cellTest.contentView.addConstraints([constraintWidth, constraintHeight, constraintCentreX, constraintCentreY ])
}

Related

UIScrollView is not scrolling after end of screen

I am trying to work with UIScrollView which I am adding programatically with auto layouts. I read other SO answers but none of them is working for me. My ScollView is scrolling but upto some point. After that end of the last child view is not showing. What i did was ,added a contentView to the UIScrollView and added subviews to the contentView. All the subviews are
translatesAutoresizingMaskIntoConstraints=false which is supposed t give me contentSize based on the constraints of the views but it is not. I tried locking the bottom of the contentView to the scrollview and also the bottom of the last subview of the contentview to the scrollview but it not working. Basically there are cards in the contentView which has height constraints. But they are not scrolling to the end. Last child is not scrolled to the end no matter what I do. What can be wrong with this approach?
class NodeSettingViewController: UIViewController,UIScrollViewDelegate {
var scrollView:UIScrollView?
var cellVM:NodeAppCellViewModel?
var contentView:UIView?
override func viewDidLoad() {
super.viewDidLoad()
let img = UIImage(named: "back_arrow")
let size = CGSize(width: 20, height: 20)
UIGraphicsBeginImageContext(size)
img!.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let backButton = UIBarButtonItem(image: image, style: UIBarButtonItemStyle.plain, target: self, action: #selector(closeButtonTapped(_:)))
self.view.backgroundColor = UIColor.white
let appBar = MDCAppBarViewController()
appBar.headerStackView.backgroundColor = UIColor(netHex: Constants.color)
appBar.navigationBar.titleAlignment = .center
appBar.navigationBar.titleTextColor = UIColor.white
appBar.navigationBar.backItem = backButton
appBar.navigationBar.title = cellVM!.appName == nil ? "" : cellVM!.appName!
view.addSubview(appBar.view)
scrollView = UIScrollView()
scrollView!.translatesAutoresizingMaskIntoConstraints=false
contentView = UIView()
contentView!.backgroundColor = UIColor(netHex: Constants.BACKGROUUND_COLOR)
contentView!.translatesAutoresizingMaskIntoConstraints=false
let statusAndImageHolder = StatusAndImageHolderView()
statusAndImageHolder.translatesAutoresizingMaskIntoConstraints=false
statusAndImageHolder.setup(cellVM: cellVM)
contentView!.addSubview(statusAndImageHolder)
let healthCard = HealthCard()
healthCard.setShadowElevation(ShadowElevation.cardResting, for: UIControlState.normal)
healthCard.translatesAutoresizingMaskIntoConstraints=false
healthCard.setup(hubID: cellVM!.nodeApp!.hubId!, nodeID: cellVM!.nodeApp!.nodeId!,nApp: cellVM!.nodeApp)
let upperConstaintHealthCard = NSLayoutConstraint(item: healthCard, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: contentView!.subviews[contentView!.subviews.count-1], attribute: NSLayoutAttribute.bottom, multiplier: 1, constant:10)
let leftConstraintHealthCard = NSLayoutConstraint(item: healthCard, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: contentView, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 10)
let rightConstraintHealthCard = NSLayoutConstraint(item: healthCard, attribute: NSLayoutAttribute.right, relatedBy: NSLayoutRelation.equal, toItem: contentView, attribute: NSLayoutAttribute.right, multiplier: 1, constant: -10)
let heightConstraintHealthCard = NSLayoutConstraint(item: healthCard, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 150)
contentView!.addSubview(healthCard)
let additionalInfoCard = AdditionalInformationCard()
additionalInfoCard.translatesAutoresizingMaskIntoConstraints=false
additionalInfoCard.setShadowElevation(ShadowElevation.cardResting, for: UIControlState.normal)
additionalInfoCard.setup()
let upperConstaintAdditionalInfoCard = NSLayoutConstraint(item: additionalInfoCard, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: contentView!.subviews[contentView!.subviews.count-1], attribute: NSLayoutAttribute.bottom, multiplier: 1, constant:10)
let leftConstraintAdditionalInfoCard = NSLayoutConstraint(item: additionalInfoCard, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: contentView, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 10)
let rightConstraintAdditionalInfoCard = NSLayoutConstraint(item: additionalInfoCard, attribute: NSLayoutAttribute.right, relatedBy: NSLayoutRelation.equal, toItem: contentView, attribute: NSLayoutAttribute.right, multiplier: 1, constant: -10)
let heightConstraintAdditionalInfoCard = NSLayoutConstraint(item: additionalInfoCard, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 270)
contentView!.addSubview(additionalInfoCard)
let upperConstaintHolder = NSLayoutConstraint(item: statusAndImageHolder, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: contentView, attribute: NSLayoutAttribute.top, multiplier: 1, constant:0)
let leftConstraintHolder = NSLayoutConstraint(item: statusAndImageHolder, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: contentView, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 0)
let rightConstraintHolder = NSLayoutConstraint(item: statusAndImageHolder, attribute: NSLayoutAttribute.right, relatedBy: NSLayoutRelation.equal, toItem: contentView, attribute: NSLayoutAttribute.right, multiplier: 1, constant: -0)
let heightConstraintHolder = NSLayoutConstraint(item: statusAndImageHolder, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 150)
scrollView!.addSubview(contentView!)
scrollView!.bringSubview(toFront: contentView!)
self.view.addSubview(scrollView!)
let contentSize = UIScreen.main.bounds.size.width
let contentHeight = UIScreen.main.bounds.size.height-30
let upperConstaintScrollView = NSLayoutConstraint(item: scrollView!, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: appBar.view, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0)
let leftConstraintScrollView = NSLayoutConstraint(item: scrollView!, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 0)
let rightConstraintScrollView = NSLayoutConstraint(item: scrollView!, attribute: NSLayoutAttribute.right, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.right, multiplier: 1, constant: -0)
let bottomConstraintScrollView = NSLayoutConstraint(item: scrollView!, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: -0)
let upperConstaintContentView = NSLayoutConstraint(item: contentView!, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: scrollView!, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0)
let leftConstraintContentView = NSLayoutConstraint(item: contentView!, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: scrollView!, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 0)
let widthConstraintContentView = NSLayoutConstraint(item: contentView!, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: contentSize)
let heightConstraintContentView = NSLayoutConstraint(item: contentView!, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: contentHeight)
NSLayoutConstraint.activate([upperConstaintScrollView,leftConstraintScrollView,rightConstraintScrollView,bottomConstraintScrollView,upperConstaintContentView,leftConstraintContentView,widthConstraintContentView,heightConstraintContentView,
upperConstaintHolder,leftConstraintHolder,rightConstraintHolder,heightConstraintHolder,
upperConstaintHealthCard,leftConstraintHealthCard,rightConstraintHealthCard,heightConstraintHealthCard,upperConstaintAdditionalInfoCard,leftConstraintAdditionalInfoCard,rightConstraintAdditionalInfoCard,heightConstraintAdditionalInfoCard])
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
#objc func closeButtonTapped(_ sender:Any){
self.dismiss(animated: true, completion: nil)
}
override func viewDidLayoutSubviews() {
scrollView?.isUserInteractionEnabled=true
scrollView!.isScrollEnabled=true
scrollView!.delegate=self
scrollView!.contentSize = contentView!.frame.size
}
}
I am sharing one of my card which is the last child of the subview.
class AdditionalInformationCard: MDCCard {
var titleLabel:UILabel?
var placeIdLabel:UILabel?
var eIDLabel:UILabel?
var hubIdLabel:UILabel?
var parentIDLabel:UILabel?
var deviceAddressLabel:UILabel?
var appIDLabel:UILabel?
var firmwareVersionLabel:UILabel?
var addedOnLabel:UILabel?
override func awakeFromNib() {
super.awakeFromNib()
}
func setup(){
let cardWidth = UIScreen.main.bounds.size.width-20
let contentWidth = cardWidth-20
titleLabel = UILabel()
titleLabel?.font = UIFont.boldSystemFont(ofSize: 18.0)
titleLabel?.textColor = UIColor(netHex: Constants.color)
titleLabel?.textAlignment = .left
titleLabel?.text = "Additional Information"
titleLabel?.translatesAutoresizingMaskIntoConstraints=false
self.addSubview(titleLabel!)
placeIdLabel = UILabel()
placeIdLabel?.textColor = UIColor.gray
placeIdLabel?.text = "Place Id"
placeIdLabel?.translatesAutoresizingMaskIntoConstraints=false
self.addSubview(placeIdLabel!)
eIDLabel = UILabel()
eIDLabel?.textColor = UIColor.gray
eIDLabel?.text = "eId"
eIDLabel?.translatesAutoresizingMaskIntoConstraints=false
self.addSubview(eIDLabel!)
hubIdLabel = UILabel()
hubIdLabel?.textColor = UIColor.gray
hubIdLabel?.text = "HUB Id"
hubIdLabel?.translatesAutoresizingMaskIntoConstraints=false
self.addSubview(hubIdLabel!)
parentIDLabel = UILabel()
parentIDLabel?.textColor = UIColor.gray
parentIDLabel?.text = "Parent Id"
parentIDLabel?.translatesAutoresizingMaskIntoConstraints=false
self.addSubview(parentIDLabel!)
deviceAddressLabel = UILabel()
deviceAddressLabel?.textColor = UIColor.gray
deviceAddressLabel?.text = "Device Address"
deviceAddressLabel?.translatesAutoresizingMaskIntoConstraints=false
self.addSubview(deviceAddressLabel!)
appIDLabel = UILabel()
appIDLabel?.textColor = UIColor.gray
appIDLabel?.text = "App Id"
appIDLabel?.translatesAutoresizingMaskIntoConstraints=false
self.addSubview(appIDLabel!)
firmwareVersionLabel = UILabel()
firmwareVersionLabel?.textColor = UIColor.gray
firmwareVersionLabel?.text = "Firmware Version"
firmwareVersionLabel?.translatesAutoresizingMaskIntoConstraints=false
self.addSubview(firmwareVersionLabel!)
addedOnLabel = UILabel()
addedOnLabel?.textColor = UIColor.gray
addedOnLabel?.text = "Added On"
addedOnLabel?.translatesAutoresizingMaskIntoConstraints=false
self.addSubview(addedOnLabel!)
let upperConstraintTitle = NSLayoutConstraint(item: titleLabel!, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 5)
let leftConstraintTitle = NSLayoutConstraint(item: titleLabel!, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 10)
let rightConstraintTitle = NSLayoutConstraint(item: titleLabel!, attribute: NSLayoutAttribute.right, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.right, multiplier: 1, constant: 10)
let heightConstraintTitle = NSLayoutConstraint(item: titleLabel!, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 20)
let upperConstraintPlaceId = NSLayoutConstraint(item: placeIdLabel!, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: titleLabel!, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 10)
let leftConstraintPlaceId = NSLayoutConstraint(item: placeIdLabel!, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 10)
let widthConstraintPlaceId = NSLayoutConstraint(item: placeIdLabel!, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: contentWidth/2)
let heightConstraintPlaceId = NSLayoutConstraint(item: placeIdLabel!, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 20)
let upperConstrainteId = NSLayoutConstraint(item: eIDLabel!, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: placeIdLabel!, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 8)
let leftConstrainteId = NSLayoutConstraint(item: eIDLabel!, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 10)
let widthConstrainteId = NSLayoutConstraint(item: eIDLabel!, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: contentWidth/2)
let heightConstrainteId = NSLayoutConstraint(item: eIDLabel!, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 20)
let upperConstraintHubIdLabel = NSLayoutConstraint(item: hubIdLabel!, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: eIDLabel!, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 8)
let leftConstraintHubIdLabel = NSLayoutConstraint(item: hubIdLabel!, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 10)
let widthConstraintHubIdLabel = NSLayoutConstraint(item: hubIdLabel!, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: contentWidth/2)
let heightConstraintHubIdLabel = NSLayoutConstraint(item: hubIdLabel!, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 20)
let upperConstraintParentIdLabel = NSLayoutConstraint(item: parentIDLabel!, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: hubIdLabel!, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 8)
let leftConstraintParentIdLabel = NSLayoutConstraint(item: parentIDLabel!, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 10)
let widthConstraintParentIdLabel = NSLayoutConstraint(item: parentIDLabel!, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: contentWidth/2)
let heightConstraintParentIdLabel = NSLayoutConstraint(item: parentIDLabel!, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 20)
let upperConstraintDeiveAddressLabel = NSLayoutConstraint(item: deviceAddressLabel!, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: parentIDLabel!, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 8)
let leftConstraintDeiveAddressLabel = NSLayoutConstraint(item: deviceAddressLabel!, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 10)
let widthConstraintDeiveAddressLabel = NSLayoutConstraint(item: deviceAddressLabel!, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: contentWidth/2)
let heightConstraintDeiveAddressLabel = NSLayoutConstraint(item: deviceAddressLabel!, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 20)
let upperConstraintAppId = NSLayoutConstraint(item: appIDLabel!, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: deviceAddressLabel!, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 8)
let leftConstraintAppId = NSLayoutConstraint(item: appIDLabel!, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 10)
let widthConstraintAppId = NSLayoutConstraint(item: appIDLabel!, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: contentWidth/2)
let heightConstraintAppId = NSLayoutConstraint(item: appIDLabel!, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 20)
let upperConstraintFirmwareVersion = NSLayoutConstraint(item: firmwareVersionLabel!, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: appIDLabel!, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 8)
let leftConstraintFirmwareVersion = NSLayoutConstraint(item: firmwareVersionLabel!, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 10)
let widthConstraintFirmwareVersion = NSLayoutConstraint(item: firmwareVersionLabel!, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: contentWidth/2)
let heightConstraintFirmwareVersion = NSLayoutConstraint(item: firmwareVersionLabel!, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 20)
let upperConstraintAddedOn = NSLayoutConstraint(item: addedOnLabel!, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: firmwareVersionLabel!, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 8)
let leftConstraintAddedOn = NSLayoutConstraint(item: addedOnLabel!, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 10)
let widthConstraintAddedOn = NSLayoutConstraint(item: addedOnLabel!, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: contentWidth/2)
let heightConstraintAddedOn = NSLayoutConstraint(item: addedOnLabel!, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 20)
NSLayoutConstraint.activate([upperConstraintTitle,leftConstraintTitle,rightConstraintTitle,heightConstraintTitle,
upperConstraintPlaceId,leftConstraintPlaceId,widthConstraintPlaceId,heightConstraintPlaceId,
upperConstrainteId,leftConstrainteId,widthConstrainteId,heightConstrainteId,
upperConstraintHubIdLabel,leftConstraintHubIdLabel,widthConstraintHubIdLabel,heightConstraintHubIdLabel,
upperConstraintParentIdLabel,leftConstraintParentIdLabel,widthConstraintParentIdLabel,heightConstraintParentIdLabel,upperConstraintDeiveAddressLabel,leftConstraintDeiveAddressLabel,widthConstraintDeiveAddressLabel,heightConstraintDeiveAddressLabel,
upperConstraintAppId,leftConstraintAppId,widthConstraintAppId,heightConstraintAppId,
upperConstraintFirmwareVersion,leftConstraintFirmwareVersion,widthConstraintFirmwareVersion,heightConstraintFirmwareVersion,upperConstraintAddedOn,leftConstraintAddedOn,widthConstraintAddedOn,heightConstraintAddedOn])
}
}

Message bubble constraints with swift

I know this is a hard problem to debug. I will try to explain, you can ask question from comments section.
I want to use message bubbles in my app. I wrote some code for constraints, but it is not working well.
How can i put the left edge of blue bubble to red line?
Here is my code:
When tableview cell loads this method is running:
private func setup() {
bubbleImageView = UIImageView(image: bubbleImage.incoming, highlightedImage: bubbleImage.incomingHighlighed)
bubbleImageView.userInteractionEnabled = true
messageLabel = UILabel(frame: CGRectZero)
messageLabel.font = UIFont.systemFontOfSize(15)
messageLabel.numberOfLines = 0
messageLabel.userInteractionEnabled = true
selectionStyle = .None
contentView.addSubview(bubbleImageView)
bubbleImageView.addSubview(messageLabel)
messageLabel.translatesAutoresizingMaskIntoConstraints = false
bubbleImageView.translatesAutoresizingMaskIntoConstraints = false
contentView.addConstraint(NSLayoutConstraint(item: bubbleImageView, attribute: .Left, relatedBy: .Equal, toItem: contentView, attribute: .Left, multiplier: 1, constant: 10))
contentView.addConstraint(NSLayoutConstraint(item: bubbleImageView, attribute: .Top, relatedBy: .Equal, toItem: contentView, attribute: .Top, multiplier: 1, constant: 4.5))
bubbleImageView.addConstraint(NSLayoutConstraint(item: bubbleImageView, attribute: .Width, relatedBy: .Equal, toItem: messageLabel, attribute: .Width, multiplier: 1, constant: 30))
contentView.addConstraint(NSLayoutConstraint(item: bubbleImageView, attribute: .Bottom, relatedBy: .Equal, toItem: contentView, attribute: .Bottom, multiplier: 1, constant: -4.5))
bubbleImageView.addConstraint(NSLayoutConstraint(item: messageLabel, attribute: .CenterX, relatedBy: .Equal, toItem: bubbleImageView, attribute: .CenterX, multiplier: 1, constant: -2))
bubbleImageView.addConstraint(NSLayoutConstraint(item: messageLabel, attribute: .CenterY, relatedBy: .Equal, toItem: bubbleImageView, attribute: .CenterY, multiplier: 1, constant: -0.5))
messageLabel.preferredMaxLayoutWidth = 218
bubbleImageView.addConstraint(NSLayoutConstraint(item: messageLabel, attribute: .Height, relatedBy: .Equal, toItem: bubbleImageView, attribute: .Height, multiplier: 1, constant: -15))
}
As you can see i am creating bubble background and label for text.
And second method:
func setCell(message:Message) {
messageLabel.text="testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest"
var layoutAttribute: NSLayoutAttribute
var layoutConstant: CGFloat
if message.incoming {
bubbleImageView.image=bgImage.incoming
messageLabel.textColor = UIColor.blackColor()
layoutAttribute = .Left
layoutConstant = 10
}else{
if message.isSent == 1 {
bubbleImageView.image = bgImage.outgoing
}
if message.isSent == 0 {
bubbleImageView.image = bgImage.notYetSent
}
messageLabel.textColor = UIColor.whiteColor()
layoutAttribute = .Right
layoutConstant = -10
}
contentView.addConstraint(NSLayoutConstraint(item: bubbleImageView, attribute: layoutAttribute, relatedBy: .Equal, toItem: contentView, attribute: layoutAttribute, multiplier: 1, constant: layoutConstant))
}
What is the problem with my code? It is working well for incoming messages (gray bubble) and not working well for outgoing messages (blue bubble)
I get it. You have to add a constraint that doesnt allows the bubble to exceed the max width. So you have to add a constraint like that:
let widthConstraint = NSLayoutConstraint(item: youritem, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.LessThanOrEqual,
toItem: self.youItem.superview, attribute: NSLayoutAttribute.Width,
multiplier: 1.0, constant: 100)

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

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.

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