PinLayout icon indicating copy to clipboard operation
PinLayout copied to clipboard

Edge offsets (.top(x), .bottom(x), .start(x), .end(x)) aren't used in autoSizeThatFits

Open constantine-fry opened this issue 7 months ago • 1 comments

hi Luc,

Thanks for working on such a great framework. It's hard to find a layout framework that doesn't use auto layout these days.

I was testing your frameworks and came across one issues. The framework calculates incorrect intrinsic size for a view that uses edge pins such as (.top, .bottom, .start, .end).

For instance, I wanted to make the following layout:

Screenshot 2023-11-27 at 21 14 02

The red line represents the bounding box of the view controller. The black line represents the bounding box of the view with the content. The demonstration purposes I used two black boxes as content.

I wrote the following code:

private final class ViewController: UIViewController {

  private let cellView: TestCellView

  init() {
    self.cellView = TestCellView()
    cellView.layer.borderColor = UIColor.black.cgColor
    cellView.layer.borderWidth = 1
    super.init()
  }

  required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  override func viewDidLoad() {
    super.viewDidLoad()
    self.view.backgroundColor = .white
    self.view.addSubview(cellView)
  }

  override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    let size = cellView.sizeThatFits(self.view.bounds.size)
    cellView.frame = CGRectMake(0, view.bounds.height / 2 - size.height / 2, size.width, size.height)
  }
}

private final class TestCellView: UIView {
  
  private let view1: UIView
  private let view2: UIView
  
  init() {
    self.view1 = UIView()
    self.view2 = UIView()
    
    super.init(frame: .zero)
    
    self.view1.backgroundColor = .black
    self.view2.backgroundColor = .black
    
    self.addSubview(view1)
    self.addSubview(view2)
  }
  
  required init?(coder: NSCoder) {
    fatalError()
  }
  
  override func layoutSubviews() {
    super.layoutSubviews()
    self.performPinLayout()
  }
  
  private func performPinLayout() {
    view1.pin
      .size(CGSize(width: 50, height: 50))
      .start(16)
      .top(16)
      .bottom(16)
    
    view2.pin
      .size(CGSize(width: 50, height: 50))
      .top(16)
      .end(16)
      .bottom(16)
  }
  
  override func sizeThatFits(_ size: CGSize) -> CGSize {
    autoSizeThatFits(size, layoutClosure: performPinLayout)
  }
}

The framework made the following layout: Screenshot 2023-11-27 at 21 14 22

Note two issues:

  1. there is a gap between red and black lines on the right side of the image.
  2. there is no margin at the bottom of the boxes.

I assume it happens because PEdgeInsets is created without _top, _bottom, _left and _right values. https://github.com/layoutBox/PinLayout/blob/master/Sources/Impl/PinLayout%2BLayouting.swift#L138

Let me know if you need additional input from me.

Thanks, C.

constantine-fry avatar Nov 27 '23 21:11 constantine-fry