0

I found a great tutorial that explained a good but on how to use PureLayout to do some cool and easy layout stuff. I'm having some trouble getting my label to align itself to the right of the view I'm attempting to put it in though

I have this in the top of the class

var cardView: UIView!
var clipView: UIView!
var scrollView: UIScrollView!

...

And then I have this in the viewDidLoad()

var openNowLabelView: UIView!
var openNowLabel: UILabel!

cardView = UIView(frame: CGRect.zero)
cardView.layer.shadowColor = UIColor.black.cgColor
cardView.layer.shadowOffset = CGSize(width: 0, height: 12)
cardView.layer.shadowOpacity = 0.33
cardView.layer.shadowRadius = 8
cardView.layer.shadowPath = UIBezierPath(roundedRect: cardView.bounds, cornerRadius: 12).cgPath

self.addSubview(cardView)

clipView = UIView(frame: CGRect.zero)
clipView.backgroundColor = UIColor(red: 42/255, green: 46/255, blue: 61/255, alpha: 1)
clipView.layer.cornerRadius = 12.0
clipView.clipsToBounds = true

cardView.addSubview(clipView)

scrollView = UIScrollView(frame: CGRect.zero)

clipView.addSubview(scrollView)

...

openNowLabelView = UIView(frame: CGRect.zero)
openNowLabel = UILabel(frame: CGRect.zero)
openNowLabel.textColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.5)
openNowLabel.font = UIFont(name: "Gibson-Regular", size: 18)
openNowLabel.text = "Open Now"
openNowLabelView.layer.borderWidth = 1
openNowLabelView.layer.borderColor = UIColor.red.cgColor
openNowLabel.textAlignment = .right

openNowLabelView.addSubview(openNowLabel)
scrollView.addSubview(openNowLabelView)

And I have a override func updateConstraints() function

if(shouldSetupConstraints) {
  cardView.autoPinEdge(toSuperviewEdge: .bottom, withInset: edgesInset)
  cardView.autoPinEdge(toSuperviewEdge: .left, withInset: edgesInset)
  cardView.autoPinEdge(toSuperviewEdge: .right, withInset: edgesInset)
  cardView.autoSetDimension(.height, toSize: UIScreen.main.bounds.height - 32)

  clipView.autoPinEdge(.top, to: .top, of: cardView)
  clipView.autoPinEdge(.left, to: .left, of: cardView)
  clipView.autoPinEdge(.right, to: .right, of: cardView)
  clipView.autoPinEdge(.bottom, to: .bottom, of: cardView)

  scrollView.autoPinEdge(.top, to: .top, of: clipView, withOffset: 161)
  scrollView.autoPinEdge(.bottom, to: .bottom, of: clipView)
  scrollView.autoPinEdge(.left, to: .left, of: clipView)
  scrollView.autoPinEdge(.right, to: .right, of: clipView)

  ...

  openNowLabel.sizeToFit()
  openNowLabelView.autoSetDimension(.height, toSize: openNowLabel.bounds.height)
  openNowLabelView.autoSetDimension(.width, toSize: openNowLabel.bounds.width)
  openNowLabelView.autoPinEdge(.right, to: .right, of: scrollView, withOffset: edgesInset)
  openNowLabelView.autoPinEdge(.top, to: .top, of: placeDistanceLabelView)
  shouldSetupConstraints = false
}
super.updateConstraints()

This is the result I'm getting looks like this...

enter image description here

I'm not understanding why this is happening

UPDATE

I've cleaned up the views and labels a bit to try to make it more clear, I was able to get around the issue I was having where I needed to embed the labels in views to make the PureLayout library work, hopefully this can better illustrate what my code says to what I'm seeing on screen

// setup views and labels
...
var scrollView: UIScrollView = {
    let view = UIScrollView.newAutoLayout()
    view?.translatesAutoresizingMaskIntoConstraints = false
    return view!
}()
...
var placeTitleLabel: UILabel = {
    let label = UILabel.newAutoLayout()
    label?.numberOfLines = 1
    label?.lineBreakMode = .byClipping
    label?.textColor = .white
    label?.font = UIFont(name: "Gibson-Semibold", size: 25)
    return label!
}()
var placeDistanceLabel: UILabel = {
    let label = UILabel.newAutoLayout()
    label?.numberOfLines = 1
    label?.lineBreakMode = .byClipping
    label?.textColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.5)
    label?.font = UIFont(name: "Gibson-Regular", size: 18)
    return label!
}()
var placeNumReviewsLabel: UILabel = {
    let label = UILabel.newAutoLayout()
    label?.numberOfLines = 1
    label?.lineBreakMode = .byClipping
    label?.textColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.5)
    label?.font = UIFont(name: "Gibson-Regular", size: 12)
    return label!
}()
var openNowLabel: UILabel = {
    let label = UILabel.newAutoLayout()
    label?.numberOfLines = 1
    label?.lineBreakMode = .byClipping
    label?.textColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.5)
    label?.font = UIFont(name: "Gibson-Regular", size: 18)
    label?.text = "Open Now"
    label?.textAlignment = .right
    return label!
}()

// constraints
placeTitleLabel.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)
placeTitleLabel.autoPinEdge(.top, to: .top, of: scrollView, withOffset: edgesInset)
placeTitleLabel.autoPinEdge(.left, to: .left, of: scrollView, withOffset: edgesInset)

placeDistanceLabel.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)
placeDistanceLabel.autoPinEdge(.left, to: .left, of: scrollView, withOffset: edgesInset)
placeDistanceLabel.autoPinEdge(.top, to: .bottom, of: placeTitleLabel, withOffset: edgesInset / 2)

placeNumReviewsLabel.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)
placeNumReviewsLabel.autoPinEdge(.left, to: .right, of: ratingView, withOffset: edgesInset)
placeNumReviewsLabel.autoPinEdge(.top, to: .top, of: ratingView, withOffset: -2)

openNowLabel.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)
openNowLabel.autoPinEdge(.trailing, to: .trailing, of: scrollView, withOffset: edgesInset)
openNowLabel.autoPinEdge(.top, to: .top, of: placeDistanceLabel)

As far as I can tell in the inspector when I highlight the scrollView the labels are embedded in it have the full width of my container there, and the label itself seems to have a width and such, I'm just not sure why I can't align the right edge, the left edge has no problems.

When I inspect the simulator I see this icon next to the openNowLabel but I'm not sure what it means or how I can get information on it, does this have something to do with my issue?

enter image description here

Here is a link to the repo I uploaded with all the pods necessary to run and see what I'm seeing if the original context will help it make sense

https://github.com/Jordan4jc/place-app-test

Jordan
  • 2,393
  • 4
  • 30
  • 60
  • Your scroll view, does it have content? Also, have you tried inspecting the view hierarchy on Xcode? Usually it is a good place to understand what is happening in these cases. – Adri May 11 '18 at 21:45
  • @Adri I did not know there was an inspector so thank you for that. The `scrollView` is what has all of these elements in it, so yes it has content and seems to have a width and height as well. I'm having trouble understanding why it's rendering in the position it is still though, the inspector only shows what I already see – Jordan May 11 '18 at 22:02
  • About the exclamation mark on the view hierarchy, if you select the view and then open the Size Inspector (on the right pane) it will tell you what is wrong with that label, probably it has an ambiguous layout (check this link for more info: https://apple.co/2wFK3Zx) – Adri May 14 '18 at 21:29

1 Answers1

0

From the code sample you shared, it looks like you added openNowLabel as subview of openNowLabelView, but you never set its constraints.

If I understand correctly what you are trying to achieve, you would need to pin the edges of openNowLabel to its superview (in the case openNowLabelView).

UPDATE

Based on the project you shared, looks like your scroll view and its subviews aren't getting all the needed constraints so the system knows how to calculate the content size. Take a look at this article from Apple (Technical Note TN2154):

Use constraints to lay out the subviews within the scroll view, being sure that the constraints tie to all four edges of the scroll view and do not rely on the scroll view to get their size.

Try adding these constraints and see if you get the layout you want:

openNowLabel.autoPinEdge(.left, to: .right, of: placeDistanceLabel, withOffset: edgesInset)
ratingView.autoPinEdge(.bottom, to: .bottom, of: scrollView, withOffset: edgesInset)

Note: if you only add the first constraint, your layout will look the same but the scroll view will have an ambiguous layout because it won't be able to calculate the height of the content size.

Adri
  • 530
  • 2
  • 8
  • I cleaned up the nesting of labels in views and now the labels are within the scroll view themselves but I'm still seeing this issue, I updated the OQ with clearer code and a bit more info that may help narrow down what my issue is? Appreciate your help! – Jordan May 14 '18 at 12:38