Can't position label to right edge of view using PureLayout

795 Views Asked by At

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

1

There are 1 best solutions below

1
On BEST ANSWER

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.