Skip to content

Commit 83d420d

Browse files
committed
Add documentation
1 parent c0890eb commit 83d420d

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,6 +1477,58 @@ This example centered horizontally the view B in the space remaining at the righ
14771477

14781478
<br/>
14791479

1480+
<a name="justify_align"></a>
1481+
## Automatic Sizing
1482+
Sizing views as part of the manual layout process is made with `sizeThatFits(_ size: CGSize)` where a view returns its ideal size given his parent size. Implementing sizing code has always been cumbersome because you always end up writing the same code twice, a first time for the layout and the second time for sizing. Sizing usually use the same rules layout does but implemented slightly differently because no subview `frame` should be mutated during sizing. Since `PinLayout` already takes care of the layout, it makes perfect sense to leverage it's layout engine to compute sizing.
1483+
1484+
###### Traditional example:
1485+
```swift
1486+
override func layoutSubviews() {
1487+
super.layoutSubviews()
1488+
scrollView.pin.all()
1489+
imageView.pin.top().horizontally().sizeToFit(.width).margin(margin)
1490+
textLabel.pin.below(of: imageView).horizontally().sizeToFit(.width).margin(margin)
1491+
scrollView.contentSize = CGSize(width: scrollView.bounds.width, height: textLabel.frame.maxY + margin)
1492+
}
1493+
1494+
override func sizeThatFits(_ size: CGSize) -> CGSize {
1495+
let availableSize = CGSize(width: size.width, height: CGFloat.greatestFiniteMagnitude)
1496+
return CGSize(width: size.width, height:
1497+
imageView.sizeThatFits(availableSize).height +
1498+
margin +
1499+
textLabel.sizeThatFits(availableSize).height +
1500+
margin
1501+
)
1502+
}
1503+
```
1504+
1505+
###### Usage examples:
1506+
```swift
1507+
override func layoutSubviews() {
1508+
super.layoutSubviews()
1509+
performLayout()
1510+
didPerformLayout()
1511+
}
1512+
1513+
private func performLayout() {
1514+
scrollView.pin.all()
1515+
imageView.pin.top().horizontally().sizeToFit(.width).margin(margin)
1516+
textLabel.pin.below(of: imageView).horizontally().sizeToFit(.width).margin(margin)
1517+
}
1518+
1519+
private func didPerformLayout() {
1520+
scrollView.contentSize = CGSize(width: scrollView.bounds.width, height: textLabel.frame.maxY + margin)
1521+
}
1522+
1523+
override func sizeThatFits(_ size: CGSize) -> CGSize {
1524+
autoSizeThatFits(size, layoutClosure: performLayout)
1525+
}
1526+
```
1527+
1528+
By calling `autoSizeThatFits` with the given available size and a layout closure, any layouting performed by PinLayout in that closure will be computed without affecting any subview's `frame` in the view hierarchy. On the other hand, any non PinLayout related code will also be executed, for that reason, it is really important to isolate your layout code in a separate function to avoid any side effect from occuring during sizing, like setting the scroll view's content size in the above exemple or assigning `itemSize` in collection view layout for exemple. That kind of code that depends on the layout should only be executed when `layoutSubviews()` is called as part of a normal layout pass.
1529+
1530+
The resulting size also takes into account the margins applied on subviews, even on the bottom and trailing sides. Automatic sizing makes it really easy to write your layout logic once and add proper sizing behavior with virtually no additional effort.
1531+
14801532
<a name="uiview_transform"></a>
14811533
## UIView's transforms
14821534

0 commit comments

Comments
 (0)