+
+```swift
+ view.pin.verticallyBetween(viewA, and: viewB, aligned: .center).marginVertical(10)
+```
+
+See [Readme for more information](https://github.com/layoutBox/PinLayout#layout_between)
+
+
+* Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#172](https://github.com/layoutBox/PinLayout/pull/172)
+
+## [1.8.2](https://github.com/layoutBox/PinLayout/releases/tag/1.8.2)
+Released on 2018-08-25
+
+#### Add `pin.readableMargins` and `pin.layoutmargins`
+Add properties:
+
+* **`pin.readableMargins: UIEdgeInset`**:
+PinLayout's `UIView.pin.readableMargins` property expose UIKit [`UIView.readableContentGuide`](https://developer.apple.com/documentation/uikit/uiview/1622644-readablecontentguide) as an UIEdgeInsets. This is really useful since UIKit only expose the readableContent area to Auto Layout using UILayoutGuide.
+
+* **`pin.layoutmargins: UIEdgeInset`**
+PinLayout's `UIView.pin.layoutMargins` property expose directly the value of UIKit [`UIView.layoutMargins`](https://developer.apple.com/documentation/uikit/uiview/1622566-layoutmargins). The property exists only to be consistent with the other areas: `pin.safeArea`, `pin.readableMargins` and `pin.layoutmargins`. So its usage is not necessary.
+
+**Add examples using these properties:**
+
+
+
+
+* Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#170](https://github.com/layoutBox/PinLayout/pull/170)
+
+## [1.8.1](https://github.com/layoutBox/PinLayout/releases/tag/1.8.1)
+Released on 2018-08-23
+
+#### PinLayout Swift 3 support
+PinLayout supports Swift 3 and Swift 4
+
+* Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#169](https://github.com/layoutBox/PinLayout/pull/169)
+
+
+## [1.8.0](https://github.com/layoutBox/PinLayout/releases/tag/1.8.0)
+Released on 2018-08-21
+
+#### Deprecated method `fitSize()` has been removed
+`fitSize()` has been removed after being deprecated for 10 months. `sizeToFit(:FitType)` should now be used instead. See [Adjusting size](https://github.com/layoutBox/PinLayout#adjusting_size).
+
+Plus:
+
+* Refactor relative positioning methods source code (above(...), after(...), ...) using a default parameter value for the alignment parameter.
+* Fix unit test screen density.
+* Update few examples source code.
+
+
+* Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#167](https://github.com/layoutBox/PinLayout/pull/167)
+
+
+## [1.7.12](https://github.com/layoutBox/PinLayout/releases/tag/1.7.12)
+Released on 2018-08-16
+
+#### Add Animations documentation and example
+Add documentation that explains how PinLayout can handle view's animations.
+
+* Show few strategies that can be used to animate views.
+* Add an Animation example in the Example app.
+* Add an new "Examples" markdown page showing all PinLayout's examples.
+* Convert `fileprivate` to `private` declarations
+
+* Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#165](https://github.com/layoutBox/PinLayout/pull/165)
+
+
+## [1.7.11](https://github.com/layoutBox/PinLayout/releases/tag/1.7.11)
+Released on 2018-08-05
+
+#### Method that position multiple edges now accept an `offset` parameter.
+The `offset` parameter that specifies the distance from their superview's corresponding edges in pixels.
+
+**New methods:**
+
+* `topLeft(_ offset: CGFloat)`
+* `topCenter(_ topOffset: CGFloat)`
+* `topRight(_ offset: CGFloat)`
+
+* `centerLeft(_ leftOffset: CGFloat)`
+* `center(_ offset: CGFloat)`
+* `centerRight(_ rightOffset offset: CGFloat)`
+
+* `bottomLeft(_ offset: CGFloat)`
+* `bottomCenter(_ bottomOffset: CGFloat)`
+* `bottomRight(_ offset: CGFloat)`
+
+For example, to position a view at the top left corner with a top and left margin of 10 pixels:
+
+```
+ view.pin.topLeft(10)
+```
+
+#### Other change
+Cleanup the interface by using default value parameters.
+
+* Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#163](https://github.com/layoutBox/PinLayout/pull/163)
+
+
+## [1.7.10](https://github.com/layoutBox/PinLayout/releases/tag/1.7.10)
+Released on 2018-07-17
+
+#### Add `sizeToFit()` method.
+The method adjust the view's size based on the result of the method `UIView.sizeToFit()`. Particularly useful for controls/views that have an intrinsic size (label, button, ...).
+
+* Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#158](https://github.com/layoutBox/PinLayout/pull/158)
+
+
+## [1.7.9](https://github.com/layoutBox/PinLayout/releases/tag/1.7.9)
+Released on 2018-06-28
+
+#### Fix a regression
+The recent changes to PinLayout that enable the layout of CALayer has impacted the layout of UIViews.
+
+* Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#152](https://github.com/layoutBox/PinLayout/pull/152)
+
+
+## [1.7.8](https://github.com/layoutBox/PinLayout/releases/tag/1.7.8)
+Released on 2018-06-26
+
+#### Add support for CALayer layout
+PinLayout can now layouts **CALayer**'s. All PinLayout's properties and methods are available, with the following exceptions:
+
+* `sizeToFit(:FitType)` is not supported. Support for `sizeToFit(:FitType)` can be added to your custom CALayer subclasses, just make those layers conform to the `SizeCalculable` protocol and implement the two required functions.
+* `CALayer.pin.safeArea` property is not available.
+* `aspectRatio()` with no parameters
+
+See [CALayer Support documentation](https://github.com/layoutBox/PinLayout#calayer-support) for more information
+
+* Added by [Antoine Lamy](https://github.com/antoinelamy) in Pull Request [#151](https://github.com/layoutBox/PinLayout/pull/151)
+
+
+## [1.7.7](https://github.com/layoutBox/PinLayout/releases/tag/1.7.6)
+Released on 2018-06-19
+
+#### Refactoring using generics
+Refactoring to avoid having to deal directly with view types, making it easier to extend layouting to other APIs (e.g: CALayer)
+
+* Added by [Antoine Lamy](https://github.com/antoinelamy) in Pull Request [#148](https://github.com/layoutBox/PinLayout/pull/148)
+
+
+## [1.7.6](https://github.com/layoutBox/PinLayout/releases/tag/1.7.6)
+Released on 2018-06-12
+
+### PinLayout has moved to the **layoutBox** organization
+PinLayout is now part of the same organization as other open source projects related to layout using Swift.
+
+#### Refactor source code that handle size adjustment.
+* Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#143](https://github.com/layoutBox/PinLayout/pull/143)
+
+#### Add an example using `wrapContent()` methods
+* Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#145](https://github.com/layoutBox/PinLayout/pull/145)
+
+#### Refactor views frame/bounds access
+* Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#147](https://github.com/layoutBox/PinLayout/pull/147)
+
+
+
+## [1.7.5](https://github.com/layoutBox/PinLayout/releases/tag/1.7.5)
+Released on 2018-06-05
+
+### Add `wrapContent()` methods that adjust view's width & height to wrap all its subviews
+
+The following methods are useful to adjust view's width and/or height to wrap all its subviews. These methods also adjust subviews position to create a tight wrap.
+
+**Methods:**
+
+* **`wrapContent()`**
+**`wrapContent(padding: CGFloat)`**
+**`wrapContent(padding: UIEdgeInsets)`**
+Adjust the view's width and height to wrap all its subviews. The method also adjusts subviews position to create a tight wrap. It is also possible to specify an optional padding around all subviews.
+* **`wrapContent(:WrapType)`**
+**`wrapContent(:WrapType, padding: CGFloat)`**
+**`wrapContent(:WrapType, padding: UIEdgeInsets)`**
+Adjust the view's width AND/OR height to wrap all its subviews. WrapType values are `.horizontally`/`.vertically`/`.all` It is also possible to specify an optional padding around all subviews.
+
+See [documentation](https://github.com/layoutBox/PinLayout#wrapContent) for more information
+
+Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#141](https://github.com/layoutBox/PinLayout/pull/141)
+
+
+## [1.7.4](https://github.com/layoutBox/PinLayout/releases/tag/1.7.4)
+Released on 2018-05-26
+
+### Objective-C support for macOS and tvOS
+Add the support of Objective-C to macOS and tvOS.
+
+Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#138](https://github.com/layoutBox/PinLayout/pull/138)
+
+## [1.7.3](https://github.com/layoutBox/PinLayout/releases/tag/1.7.3)
Released on 2018-04-25
### Add few missing Objective-C Interface properties and methods
@@ -18,10 +409,10 @@ These methods and properties are now accessible from Objective-C:
* `Pin.initPinLayout()`
* `Pin.layoutDirection()`
-Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#135](https://github.com/mirego/PinLayout/pull/135)
+Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#135](https://github.com/layoutBox/PinLayout/pull/135)
-## [1.7.2](https://github.com/layoutBox/FlexLayout/releases/tag/1.7.2)
+## [1.7.2](https://github.com/layoutBox/PinLayout/releases/tag/1.7.2)
Released on 2018-04-23
### Fine tune UIView.pin.safeArea support for iOS 8 and "New Relic" framework
@@ -31,11 +422,11 @@ Changes:
* Fix issue with "New Relic" framework: Add a Pin.initPinLayout() that can be called to initialize PinLayout before the "New Relic" framework is initialized. "New Relic" is conflicting with other popular frameworks including Mixpanel, ReactiveCocoa, Aspect, ..., and PinLayout. To fix the issue, `Pin.initPinLayout()` must be called BEFORE initializing "New Relic" with `NewRelic.start(withApplicationToken:"APP_TOKEN")`. See here for more information regarding this issue #130
-Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#134](https://github.com/mirego/PinLayout/pull/134)
+Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#134](https://github.com/layoutBox/PinLayout/pull/134)
-## [1.7.0](https://github.com/layoutBox/FlexLayout/releases/tag/1.7.0)
+## [1.7.0](https://github.com/layoutBox/PinLayout/releases/tag/1.7.0)
Released on 2018-04-20
### Add macOS support
@@ -54,21 +445,21 @@ PinLayout **support of macOS is not complete at 100%**, see here the particulari
All other PinLayout's methods and properties are available on macOS!
-Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#131](https://github.com/mirego/PinLayout/pull/131)
+Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#131](https://github.com/layoutBox/PinLayout/pull/131)
### PinLayout now use MIT license
The PinLayout license has been changed from **BSD 3-clause "New"** to **MIT License**.
-## [1.6.0](https://github.com/layoutBox/FlexLayout/releases/tag/1.6.0)
+## [1.6.0](https://github.com/layoutBox/PinLayout/releases/tag/1.6.0)
Released on 2018-03-22
### UIView.pin.safeArea
PinLayout can handle easily iOS 11 UIView.safeAreaInsets, but it goes further by supporting safeAreaInsets for previous iOS releases (including iOS 7/8/9/10) by adding a property UIView.pin.safeArea. PinLayout also extend the support of UIView.safeAreaInsetsDidChange() callback on iOS 7/8/9/10.
-See [UIView.pin.safeArea Documentation](https://github.com/mirego/PinLayout#safeAreaInsets) for more details.
+See [UIView.pin.safeArea Documentation](https://github.com/layoutBox/PinLayout#safeAreaInsets) for more details.
-Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#125](https://github.com/mirego/PinLayout/pull/125)
+Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#125](https://github.com/layoutBox/PinLayout/pull/125)
### Add methods taking UIEdgeInset as parameter
@@ -80,9 +471,9 @@ Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#125](https://g
* `left(_ insets: UIEdgeInsets)`
* `right(_ insets: UIEdgeInsets)`
- See [Layout using distances from superview’s edges](https://github.com/mirego/PinLayout#layout-using-distances-from-superviews-edges) for more details.
+ See [Layout using distances from superview’s edges](https://github.com/layoutBox/PinLayout#layout-using-distances-from-superviews-edges) for more details.
- Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#125](https://github.com/mirego/PinLayout/pull/125)
+ Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#125](https://github.com/layoutBox/PinLayout/pull/125)
### Add margins method with percentage parameter
@@ -99,9 +490,9 @@ Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#125](https://g
* `margin(_ top: Percent, _ horizontal: Percent, _ bottom: Percent)`
* `margin(_ top: Percent, _ left: Percent, _ bottom: Percent, _ right: Percent)`
- Added by [vandyshev](https://github.com/vandyshev) in Pull Request [#126](https://github.com/mirego/PinLayout/pull/126)
+ Added by [vandyshev](https://github.com/vandyshev) in Pull Request [#126](https://github.com/layoutBox/PinLayout/pull/126)
-## [1.5.9](https://github.com/layoutBox/FlexLayout/releases/tag/1.5.9)
+## [1.5.9](https://github.com/layoutBox/PinLayout/releases/tag/1.5.9)
Released on 2018-02-18
#### **`UIView.pin`** versus **`UIView.pinFrame`**
@@ -111,27 +502,27 @@ Until now `UIView.pin` was used to layout views, but there's also another proper
* `.pinFrame`: Set the position and the size on the **transformed view**. The size and position is applied **after the transform**.
-See https://github.com/mirego/PinLayout#uiviews-transforms for more informations.
+See https://github.com/layoutBox/PinLayout#uiviews-transforms for more informations.
-Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#122](https://github.com/mirego/PinLayout/pull/122)
+Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#122](https://github.com/layoutBox/PinLayout/pull/122)
-## [1.5.8](https://github.com/layoutBox/FlexLayout/releases/tag/1.5.8)
+## [1.5.8](https://github.com/layoutBox/PinLayout/releases/tag/1.5.8)
Released on 2018-01-20
* Handle layout relative to a view with a transform and/or a modified anchorPoint.
-Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#116](https://github.com/mirego/PinLayout/pull/116)
+Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#116](https://github.com/layoutBox/PinLayout/pull/116)
-## [1.5.7](https://github.com/layoutBox/FlexLayout/releases/tag/1.5.7)
+## [1.5.7](https://github.com/layoutBox/PinLayout/releases/tag/1.5.7)
Released on 2018-01-19
* Fix an issue that was affecting UIScrollViews. PinLayout now set only the bounds's size and keep the origin.
-Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#115](https://github.com/mirego/PinLayout/pull/115)
+Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#115](https://github.com/layoutBox/PinLayout/pull/115)
* Handle correctly view's `layer.anchorPoint`. PinLayout now update correctly the view position when the view's layer.anchorPoint has been modified, i.e. when it is not its default value (0.5, 0.5).
-Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#114](https://github.com/mirego/PinLayout/pull/114)
+Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#114](https://github.com/layoutBox/PinLayout/pull/114)
-## [1.5.5](https://github.com/layoutBox/FlexLayout/releases/tag/1.5.5)
+## [1.5.5](https://github.com/layoutBox/PinLayout/releases/tag/1.5.5)
Released on 2018-01-12
Add methods:
@@ -147,23 +538,23 @@ Similar to calling `view.left(value).right(value)`.
* **`vertically(_ value: CGFloat)`** / **`vertically(_ percent: Percent)`**
The value specifies the ** top and bottom edges** on its superview's corresponding edges in pixels (or in percentage of its superview's height).
Similar to calling `view.top(value).bottom(value)`.
- * Added by [Olivier Pineau](https://github.com/OlivierPineau) in Pull Request [#111](https://github.com/mirego/PinLayout/pull/111)
+ * Added by [Olivier Pineau](https://github.com/OlivierPineau) in Pull Request [#111](https://github.com/layoutBox/PinLayout/pull/111)
-## [1.5.4](https://github.com/layoutBox/FlexLayout/releases/tag/1.5.4)
+## [1.5.4](https://github.com/layoutBox/PinLayout/releases/tag/1.5.4)
Released on 2017-12-28
* PinLayout now handle correctly more situations with view with transforms.
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#110](https://github.com/mirego/PinLayout/pull/110)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#110](https://github.com/layoutBox/PinLayout/pull/110)
-## [1.5.3](https://github.com/layoutBox/FlexLayout/releases/tag/1.5.3)
+## [1.5.3](https://github.com/layoutBox/PinLayout/releases/tag/1.5.3)
Released on 2017-12-28
* PinLayout now handle correctly parents (superviews) with transforms.
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#108](https://github.com/mirego/PinLayout/pull/108)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#108](https://github.com/layoutBox/PinLayout/pull/108)
-## [1.5.2](https://github.com/layoutBox/FlexLayout/releases/tag/1.5.2)
+## [1.5.2](https://github.com/layoutBox/PinLayout/releases/tag/1.5.2)
Released on 2017-12-22
* POSSIBLE BREAKING CHANGE: PinLayout now keeps UIView's transform (scale, rotation, ...)
@@ -171,22 +562,22 @@ Previously any view's transform was altered after layouting the view with PinLay
For people not using transforms, this should be a non-breaking change. If someone is using transforms with PinLayout, this may change the behavior, although I think this will produce the expected results (ie, transforms not being affected/altered by layout).
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#107](https://github.com/mirego/PinLayout/pull/107)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#107](https://github.com/layoutBox/PinLayout/pull/107)
-## [1.5.1](https://github.com/mirego/PinLayout/releases/tag/1.5.1)
+## [1.5.1](https://github.com/layoutBox/PinLayout/releases/tag/1.5.1)
#### Change
* Add `layout()` method to support Xcode playgrounds
PinLayout layouts views immediately after the line containing `.pin` has been fully executed, thanks to ARC (Automatic Reference Counting) this works perfectly on iOS/tvOS/macOS simulators and devices. But in Xcode Playgrounds, ARC doesn't work as expected, object references are kept much longer. This is a well-documented issue. The impact of this problem is that PinLayout doesn't layout views at the time and in the order required. To handle this situation in playgrounds it is possible to call the `layout()` method to complete the layout.
-[See PinLayout in Xcode Playgrounds documentation for more information](https://github.com/mirego/PinLayout#playgrounds)
+[See PinLayout in Xcode Playgrounds documentation for more information](https://github.com/layoutBox/PinLayout#playgrounds)
-* Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#101](https://github.com/mirego/PinLayout/pull/101)
+* Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#101](https://github.com/layoutBox/PinLayout/pull/101)
-## [1.5.0](https://github.com/mirego/PinLayout/releases/tag/1.5.0)
+## [1.5.0](https://github.com/layoutBox/PinLayout/releases/tag/1.5.0)
### New method `sizeToFit(:FitType)` & `fitSize()` is now deprecated
#### Changes
@@ -216,14 +607,14 @@ PinLayout layouts views immediately after the line containing `.pin` has been fu
* **`.heightFlexible`**: Similar to `.height`, except that PinLayout won't constrain the resulting height to match the reference height. The resulting height may be smaller of bigger depending on the view's sizeThatFits(..) method result.
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#103](https://github.com/mirego/PinLayout/pull/103)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#103](https://github.com/layoutBox/PinLayout/pull/103)
-## [1.4.3](https://github.com/mirego/PinLayout/releases/tag/1.4.1)
+## [1.4.3](https://github.com/layoutBox/PinLayout/releases/tag/1.4.1)
Fix Carthage support
* Fix an issue that occurs with the latest Carthage version.
-## [1.4.2](https://github.com/mirego/PinLayout/releases/tag/1.4.1)
+## [1.4.2](https://github.com/layoutBox/PinLayout/releases/tag/1.4.1)
#### Change
Add method that can pin multiples edges:
@@ -233,10 +624,10 @@ Add method that can pin multiples edges:
* `vertically()`: Pin the **top and bottom edges** on its superview's corresponding edges. Similar to calling `view.top().bottom()`.
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#93](https://github.com/mirego/PinLayout/pull/93)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#93](https://github.com/layoutBox/PinLayout/pull/93)
-## [1.4.1](https://github.com/mirego/PinLayout/releases/tag/1.4.1)
+## [1.4.1](https://github.com/layoutBox/PinLayout/releases/tag/1.4.1)
#### Change
* Add new method `margin(_ directionalInsets: NSDirectionalEdgeInsets)`
@@ -244,12 +635,12 @@ Add method that can pin multiples edges:
This method is particularly to set all margins using iOS 11 `UIView.directionalLayoutMargins`.
Available only on iOS 11 and higher.
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#85](https://github.com/mirego/PinLayout/pull/85)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#85](https://github.com/layoutBox/PinLayout/pull/85)
* Update all examples so they support iOS 11 and iPhoneX landscape mode. They use the new UIView.safeAreaInsets property.
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#85](https://github.com/mirego/PinLayout/pull/85)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#85](https://github.com/layoutBox/PinLayout/pull/85)
-## [1.4.0](https://github.com/mirego/PinLayout/releases/tag/1.4.0)
+## [1.4.0](https://github.com/layoutBox/PinLayout/releases/tag/1.4.0)
#### Change
* PinLayout now apply correctly margins when hCenter or vCenter have been set
* hCenter: When the Horizontal Center is set, PinLayout now applies the left margin.
@@ -257,10 +648,10 @@ Add method that can pin multiples edges:
**BREAKING CHANGE**: This may be a breaking change if you are using hCenter(..), vCenter(...), center(...), centerRight(...), centerLeft(...), or any other method using the center position while also using a margin.
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#91](https://github.com/mirego/PinLayout/pull/91)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#91](https://github.com/layoutBox/PinLayout/pull/91)
-## [1.3.2](https://github.com/mirego/PinLayout/releases/tag/1.3.2)
+## [1.3.2](https://github.com/layoutBox/PinLayout/releases/tag/1.3.2)
#### Change
* Add **aspectRatio** methods:
* **`aspectRatio(_ ratio: CGFloat)`**:
@@ -285,16 +676,16 @@ This method is particularly useful to set all margins using iOS 11 UIView.safeAr
the UIImageView's image dimension.
For other types of views, this method as no impact.
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#84](https://github.com/mirego/PinLayout/pull/84)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#84](https://github.com/layoutBox/PinLayout/pull/84)
-## [1.3.1](https://github.com/mirego/PinLayout/releases/tag/1.3.1)
+## [1.3.1](https://github.com/layoutBox/PinLayout/releases/tag/1.3.1)
#### Change
* Add new margin method `margin(_ insets: UIEdgeInsets)`
Set all margins using an UIEdgeInsets.
This method is particularly useful to set all margins using iOS 11 UIView.safeAreaInsets
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#82](https://github.com/mirego/PinLayout/pull/82)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#82](https://github.com/layoutBox/PinLayout/pull/82)
-## [1.3.0](https://github.com/mirego/PinLayout/releases/tag/1.3.0)
+## [1.3.0](https://github.com/layoutBox/PinLayout/releases/tag/1.3.0)
Released on 2017-08-18.
#### Change
@@ -306,7 +697,7 @@ The value specifies the distance horizontally of the view's center **related to
Previously `hCenter(0)` wasn't equal to `hCenter()`, same thing for `vCenter(0)`. But this was an exception: `top(0)` == `top()`,` left(0)` == `left()`, `right(0)` == `right()`. Now thay all have the same logic.
-## [1.2.4](https://github.com/mirego/PinLayout/releases/tag/1.2.4)
+## [1.2.4](https://github.com/layoutBox/PinLayout/releases/tag/1.2.4)
#### Change
* Add methods to pin hCenter and vCenter to any other view's edges (including the new hCenter and vCenter edges)
* **New methods**:
@@ -317,9 +708,9 @@ Previously `hCenter(0)` wasn't equal to `hCenter()`, same thing for `vCenter(0)`
* **New UIView's edges**:
* **`UIView.edge.hCenter`**
* **`UIView.edge.vCenter`**
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#80](https://github.com/mirego/PinLayout/pull/80)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#80](https://github.com/layoutBox/PinLayout/pull/80)
-## [1.2.3](https://github.com/mirego/PinLayout/releases/tag/1.2.3)
+## [1.2.3](https://github.com/layoutBox/PinLayout/releases/tag/1.2.3)
#### Change
* Warnings now display more context information
* The class name of the view being layouted.
@@ -338,18 +729,18 @@ Previously `hCenter(0)` wasn't equal to `hCenter()`, same thing for `vCenter(0)`
* 👉 PinLayout Warning: topLeft(to: .topLeft, of: (UIView, Frame: (10.0, 10.0, 10.0, 10.0))) won't be applied, the reference view (UIView, Frame: (10.0, 10.0, 10.0, 10.0)) must be added as a sub-view before being used as a reference.
(Layouted view info: Type: UIView, Frame: (140.0, 100.0, 100.0, 60.0), Superviews: UIView -> UIView, Tag: 0)
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#75](https://github.com/mirego/PinLayout/pull/75)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#75](https://github.com/layoutBox/PinLayout/pull/75)
-## [1.2.2](https://github.com/mirego/PinLayout/releases/tag/1.2.2)
+## [1.2.2](https://github.com/layoutBox/PinLayout/releases/tag/1.2.2)
#### Change
* Added a new method `fitSize()` that will replace the `sizeThatFit()` method. Its prior name was creating confusion with the already existingUIView.sizeToFit()` method.
* `sizeThatFit()` method has been marked as deprecated.
-## [1.2.1](https://github.com/mirego/PinLayout/releases/tag/1.2.1)
+## [1.2.1](https://github.com/layoutBox/PinLayout/releases/tag/1.2.1)
#### Change
* Add Swift 4.0 support
-## [1.2.0](https://github.com/mirego/PinLayout/releases/tag/1.2.0)
+## [1.2.0](https://github.com/layoutBox/PinLayout/releases/tag/1.2.0)
Released on 2017-08-18.
#### Change
@@ -384,19 +775,19 @@ Additions:
* marginEnd(_ value: CGFloat)
* HorizontalAlign.start
* HorizontalAlign.end
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#56](https://github.com/mirego/PinLayout/pull/56)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#56](https://github.com/layoutBox/PinLayout/pull/56)
-## [1.1.5](https://github.com/mirego/PinLayout/releases/tag/1.1.5)
+## [1.1.5](https://github.com/layoutBox/PinLayout/releases/tag/1.1.5)
Released on 2017-07-14.
#### Change
* Fix missing UIKit import. The problem was occuring while using Swift Package Manager.
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#67](https://github.com/mirego/PinLayout/pull/67)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#67](https://github.com/layoutBox/PinLayout/pull/67)
-## [1.1.4](https://github.com/mirego/PinLayout/releases/tag/1.1.4)
+## [1.1.4](https://github.com/layoutBox/PinLayout/releases/tag/1.1.4)
Released on 2017-07-09.
#### Change
@@ -407,17 +798,17 @@ Released on 2017-07-09.
* maxHeight
* justify(:HorizontalAlign)
* align(:VerticalAlign)
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#53](https://github.com/mirego/PinLayout/pull/53)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#53](https://github.com/layoutBox/PinLayout/pull/53)
-## [1.1.1](https://github.com/mirego/PinLayout/releases/tag/1.1.1)
+## [1.1.1](https://github.com/layoutBox/PinLayout/releases/tag/1.1.1)
Released on 2017-06-27.
#### Change
* Support **Xcode 9 Beta 2**
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#52](https://github.com/mirego/PinLayout/pull/52)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#52](https://github.com/layoutBox/PinLayout/pull/52)
* Add a Form example
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#51](https://github.com/mirego/PinLayout/pull/51)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#51](https://github.com/layoutBox/PinLayout/pull/51)
* This example demonstrates:
* Usage of filter method when using PinLayout's relative methods (above, below, left, right)
* Adjusting a container's height to match all its children.
@@ -425,30 +816,30 @@ Released on 2017-06-27.
-## [1.1.0](https://github.com/mirego/PinLayout/releases/tag/1.1.0)
+## [1.1.0](https://github.com/layoutBox/PinLayout/releases/tag/1.1.0)
Released on 2017-06-18.
#### Change
* Update relative methods signatures when specifying multiple relative views.
Update the minor version due to a small breaking change with methods above(of…), below(of…), left(of…) and right(of…). They now takes either a single UIView or an Array of UIViews.
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#48](https://github.com/mirego/PinLayout/pull/48)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#48](https://github.com/layoutBox/PinLayout/pull/48)
-## [1.0.15](https://github.com/mirego/PinLayout/releases/tag/1.0.15)
+## [1.0.15](https://github.com/layoutBox/PinLayout/releases/tag/1.0.15)
Released on 2017-06-12.
#### Change
* Add **tvOS** support & set iOS target to 8.0 (instead of 10.2)
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#46](https://github.com/mirego/PinLayout/pull/46)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#46](https://github.com/layoutBox/PinLayout/pull/46)
-## [1.0.14](https://github.com/mirego/PinLayout/releases/tag/1.0.14)
+## [1.0.14](https://github.com/layoutBox/PinLayout/releases/tag/1.0.14)
Released on 2017-06-12.
#### Change
* Implementation of **relative positioning using multiple relative views**
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#43](https://github.com/mirego/PinLayout/pull/43)
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#43](https://github.com/layoutBox/PinLayout/pull/43)
* The following methods can now receives one or many relative views. Useful to position a view relative to many UIViews.
* `above(of relativeViews: UIView...) `
* `above(of relativeViews: UIView..., aligned: HorizontalAlignment) `
@@ -459,13 +850,13 @@ Released on 2017-06-12.
* `right(of relativeViews: UIView...) `
* `right(of relativeViews: UIView..., aligned: VerticalAlignment)`
-## [1.0.11](https://github.com/mirego/PinLayout/releases/tag/1.0.11)
+## [1.0.11](https://github.com/layoutBox/PinLayout/releases/tag/1.0.11)
Released on 2017-06-08.
#### Change
* Add **Swift Package Manager** support
- * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#38](https://github.com/mirego/PinLayout/pull/38
+ * Added by [Luc Dion](https://github.com/lucdion) in Pull Request [#38](https://github.com/layoutBox/PinLayout/pull/38
* **`size(…)` methods** now tries to apply the width and the height individually
Previously the size specified was applied only if both the width and height wasn’t specified. Now PinLayout will apply them individually, so if the width has been specified yet, the size’s width will be applied, else a warning will be displayed that indicate that the width won’t be applied. Same thing for the height.
* Doesn’t display a warning anymore if the new specified width or height value is equal to the currently set value. This is coherent with other methods (top, left, hCenter, ….)
@@ -476,13 +867,13 @@ Previously the size specified was applied only if both the width and height wasn
### Fixes
- Fix an issue with pin.vCenter() and pin.hCenter()
- Fixed by [Luc Dion](https://github.com/lucdion) in Pull Request
- [#36](https://github.com/mirego/PinLayout/pull/36).
+ [#36](https://github.com/layoutBox/PinLayout/pull/36).
-## [1.0.7](https://github.com/mirego/PinLayout/releases/tag/1.0.7)
+## [1.0.7](https://github.com/layoutBox/PinLayout/releases/tag/1.0.7)
Released on 2017-06-06.
### Fixes
- Fix an issue with pin.vCenter() and pin.hCenter()
- Fixed by [Luc Dion](https://github.com/lucdion) in Pull Request
- [#36](https://github.com/mirego/PinLayout/pull/36).
+ [#36](https://github.com/layoutBox/PinLayout/pull/36).
diff --git a/Example/.DS_Store b/Example/.DS_Store
new file mode 100644
index 00000000..b066f015
Binary files /dev/null and b/Example/.DS_Store differ
diff --git a/Example/.swiftlint.yml b/Example/.swiftlint.yml
index 0df8a810..adee2693 100644
--- a/Example/.swiftlint.yml
+++ b/Example/.swiftlint.yml
@@ -24,3 +24,4 @@ disabled_rules: # rule identifiers to exclude from running
excluded: # paths to ignore during linting. overridden by `included`.
- Pods
+ - PinLayoutExampleMacOS
\ No newline at end of file
diff --git a/Example/PinLayoutSample.xcodeproj/project.pbxproj b/Example/PinLayoutSample.xcodeproj/project.pbxproj
index 7fe03372..1db911c2 100644
--- a/Example/PinLayoutSample.xcodeproj/project.pbxproj
+++ b/Example/PinLayoutSample.xcodeproj/project.pbxproj
@@ -3,19 +3,17 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 46;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
241637741F8E4BC200EE703A /* IntroObjectiveCViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 241637711F8E4BC200EE703A /* IntroObjectiveCViewController.m */; };
241637771F8E4F9100EE703A /* IntroObjectiveCView.m in Sources */ = {isa = PBXBuildFile; fileRef = 241637761F8E4F9100EE703A /* IntroObjectiveCView.m */; };
- 2439CC281E6658C3003326FB /* PinLayout.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2439CC241E665858003326FB /* PinLayout.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
- 2439CC2B1E6658CC003326FB /* PinLayout.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2439CC241E665858003326FB /* PinLayout.framework */; };
2439CC351E665BF6003326FB /* MenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2439CC331E665BF6003326FB /* MenuView.swift */; };
2439CC361E665BF6003326FB /* MenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2439CC341E665BF6003326FB /* MenuViewController.swift */; };
2439CC4B1E665C6B003326FB /* BasicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2439CC381E665C6B003326FB /* BasicView.swift */; };
- 2439CC521E665C6B003326FB /* MultiRelativeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2439CC3F1E665C6B003326FB /* MultiRelativeView.swift */; };
- 2439CC531E665C6B003326FB /* MultiRelativeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2439CC401E665C6B003326FB /* MultiRelativeViewController.swift */; };
+ 2439CC521E665C6B003326FB /* BetweenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2439CC3F1E665C6B003326FB /* BetweenView.swift */; };
+ 2439CC531E665C6B003326FB /* BetweenViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2439CC401E665C6B003326FB /* BetweenViewController.swift */; };
2439CC541E665C6B003326FB /* RelativeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2439CC411E665C6B003326FB /* RelativeView.swift */; };
2439CC551E665C6B003326FB /* RelativeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2439CC421E665C6B003326FB /* RelativeViewController.swift */; };
247157941F87BD680003424F /* UIEdgeInsets+PinLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 247157931F87BD680003424F /* UIEdgeInsets+PinLayout.swift */; };
@@ -43,12 +41,28 @@
24F246141FA8D57100B6332E /* UIImageView+Download.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F246131FA8D57100B6332E /* UIImageView+Download.swift */; };
24F75B5B1EE5644E008DB567 /* IntroView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F75B591EE5644E008DB567 /* IntroView.swift */; };
24F75B5C1EE5644E008DB567 /* IntroViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F75B5A1EE5644E008DB567 /* IntroViewController.swift */; };
- DE6C3D736B571B80E207DF6A /* Pods_PinLayoutSample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AAD69688AA2A3F0994F3074E /* Pods_PinLayoutSample.framework */; };
+ B30A278A4301304C7DD08E37 /* Pods_PinLayoutSample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 641BBAE7F09807BD466749F3 /* Pods_PinLayoutSample.framework */; };
+ C892FA1924A5821E0086A75E /* AutoSizingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C892FA1824A5821E0086A75E /* AutoSizingViewController.swift */; };
+ C892FA1B24A5822B0086A75E /* AutoSizingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C892FA1A24A5822B0086A75E /* AutoSizingView.swift */; };
+ C892FA1D24A584010086A75E /* ContentService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C892FA1C24A584010086A75E /* ContentService.swift */; };
+ C892FA1F24A597FA0086A75E /* AutoSizingContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C892FA1E24A597FA0086A75E /* AutoSizingContainerView.swift */; };
+ C892FA2124A598170086A75E /* ProxyWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = C892FA2024A598170086A75E /* ProxyWrapper.swift */; };
+ DF390898211900320049FD56 /* AnimationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF390897211900320049FD56 /* AnimationsView.swift */; };
+ DF39089A211900480049FD56 /* AnimationsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF390899211900480049FD56 /* AnimationsViewController.swift */; };
DF4C1AA4205AEDFC00DED50B /* SafeAreaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4C1AA0205AEDFC00DED50B /* SafeAreaView.swift */; };
DF4C1AA5205AEDFC00DED50B /* SafeAreaViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4C1AA1205AEDFC00DED50B /* SafeAreaViewController.swift */; };
DF4C1AAA205AF10900DED50B /* RoundedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4C1AA7205AF10900DED50B /* RoundedButton.swift */; };
- DF4C1AAE205AF78A00DED50B /* SafeAreaCornersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4C1AAC205AF78A00DED50B /* SafeAreaCornersViewController.swift */; };
- DF4C1AAF205AF78A00DED50B /* SafeAreaCornersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4C1AAD205AF78A00DED50B /* SafeAreaCornersView.swift */; };
+ DF4C1AAE205AF78A00DED50B /* SafeAreaAndMarginsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4C1AAC205AF78A00DED50B /* SafeAreaAndMarginsViewController.swift */; };
+ DF4C1AAF205AF78A00DED50B /* SafeAreaAndMarginsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4C1AAD205AF78A00DED50B /* SafeAreaAndMarginsView.swift */; };
+ DFBCAEFB213012930025F7BF /* MethodReadableInsetsGroupHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFBCAEF9213012930025F7BF /* MethodReadableInsetsGroupHeader.swift */; };
+ DFBCAEFC213012930025F7BF /* MethodReadableInsetsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFBCAEFA213012930025F7BF /* MethodReadableInsetsCell.swift */; };
+ DFBCAEFE2130146C0025F7BF /* AreaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFBCAEFD2130146C0025F7BF /* AreaView.swift */; };
+ DFD27841211B1A710056BD93 /* UINavigationController+Orientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFD27840211B1A700056BD93 /* UINavigationController+Orientation.swift */; };
+ DFD27848211B1D090056BD93 /* UITabBarController+Orientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFD27847211B1D090056BD93 /* UITabBarController+Orientation.swift */; };
+ DFD31BA0212EE4F200566CA4 /* TableViewReadableContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFD31B9E212EE4F100566CA4 /* TableViewReadableContentView.swift */; };
+ DFD31BA1212EE4F200566CA4 /* TableViewReadableContentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFD31B9F212EE4F200566CA4 /* TableViewReadableContentViewController.swift */; };
+ DFEAF74A20C9648A00E33147 /* WrapContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFEAF74920C9648A00E33147 /* WrapContentView.swift */; };
+ DFEAF74C20C9649F00E33147 /* WrapContentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFEAF74B20C9649F00E33147 /* WrapContentViewController.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -66,13 +80,6 @@
remoteGlobalIDString = 249EFE831E64FB4C00165E39;
remoteInfo = PinLayoutTests;
};
- 2439CC291E6658C3003326FB /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 2439CC1E1E665858003326FB /* PinLayout.xcodeproj */;
- proxyType = 1;
- remoteGlobalIDString = 249EFE791E64FB4C00165E39;
- remoteInfo = PinLayout;
- };
24DA374E1EF7F90700D1AB2F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 2439CC1E1E665858003326FB /* PinLayout.xcodeproj */;
@@ -80,31 +87,28 @@
remoteGlobalIDString = 244DF2F81EF46C500090508B;
remoteInfo = PinLayoutTVOS;
};
-/* End PBXContainerItemProxy section */
-
-/* Begin PBXCopyFilesBuildPhase section */
- 2460ACCE1E64FD9D000BCAC5 /* Embed Frameworks */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "";
- dstSubfolderSpec = 10;
- files = (
- 2439CC281E6658C3003326FB /* PinLayout.framework in Embed Frameworks */,
- );
- name = "Embed Frameworks";
- runOnlyForDeploymentPostprocessing = 0;
+ DFEAF71B20C840F300E33147 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 2439CC1E1E665858003326FB /* PinLayout.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = DF1A5D2C2084CF9700725EF5;
+ remoteInfo = "PinLayout-macOS";
};
- 2468130D1F8D013600462E53 /* Embed App Extensions */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "";
- dstSubfolderSpec = 13;
- files = (
- );
- name = "Embed App Extensions";
- runOnlyForDeploymentPostprocessing = 0;
+ DFEAF71D20C840F300E33147 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 2439CC1E1E665858003326FB /* PinLayout.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = DF1A5D1D2084C94700725EF5;
+ remoteInfo = "PinLayoutTests-macOS";
+ };
+ DFEAF71F20C840F300E33147 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 2439CC1E1E665858003326FB /* PinLayout.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = DFF6F9C22084DCD3004F5AED;
+ remoteInfo = "PinLayoutTests-tvOS";
};
-/* End PBXCopyFilesBuildPhase section */
+/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
241637701F8E4BC200EE703A /* IntroObjectiveCViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntroObjectiveCViewController.h; sourceTree = "
+
-**PinLayout** is a companion of **[FlexLayout](https://github.com/layoutBox/FlexLayout)**. They share a similar syntax and method names. FlexLayout is a flexbox implementation. A view can layouts its subviews using PinLayout, FlexLayout, or both! FlexLayout it is particularly useful in situations where you need to layouts many views but don't require the PinLayout's finest control nor complex animations.
+**PinLayout** is part of the **layoutBox** organization containing few Open Source projects related to layout using Swift. See **[layoutBox](https://github.com/layoutBox)**.
### PinLayout + Autolayout
You don't need to choose, you can layout some views using PinLayout and some other with autolayout. Your views just to need to implement the autolayout `intrinsicContentSize` properties.
@@ -100,7 +104,7 @@ This example layout an image, a UISegmentedControl, a label and a line separator
* **Separator** is below the UIImageView and the UILabel, i.e. below the tallest one. The separator has a top margin of 10 pixels, left-aligned to the UIImageView and right-aligned to the UISegmentedControl.
-
+
```swift
override func layoutSubviews() {
@@ -117,7 +121,7 @@ override func layoutSubviews() {
* 4 views, 4 lines
* PinLayout expose the `safeAreaInsets` through [`UIView.pin.safeArea`](#safeAreaInsets), this property support not only iOS 11, but is also backward compatible for earlier iOS releases (7/8/9/10). See [safeAreaInsets support](#safeAreaInsets) for more information.
* PinLayout doesn't use auto layout constraints, it is a framework that manually layout views. For that reason you need to update the layout inside either `UIView.layoutSubviews()` or `UIViewController.viewDidLayoutSubviews()` to handle container size's changes, including device rotation. You'll also need to handle UITraitCollection changes for app's that support multitasking. In the example above PinLayout's commands are inside UIView's `layoutSubviews()` method.
-* This example is available in the [Examples App](#examples_app). See example complete [source code](https://github.com/mirego/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/Intro/IntroView.swift)
+* This example is available in the [Examples App](#examples_app). See example complete [source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/Intro/IntroView.swift)
+
```swift
let margin: CGFloat = 12
if frame.width < 500 {
- textLabel.pin.top().left().right().margin(margin).sizeToFit(.width)
+ textLabel.pin.top().horizontally().margin(margin).sizeToFit(.width)
segmentedControl.pin.below(of: textLabel).right().margin(margin)
} else {
segmentedControl.pin.top().right().margin(margin)
@@ -142,7 +146,7 @@ This example shows how easily PinLayout can adjust its layout based on the view'
}
```
-:pushpin: This example is available in the [Examples App](#examples_app). See example complete [source code](https://github.com/mirego/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/AdjustToContainer/Subviews/ChoiceSelectorView.swift)
+:pushpin: This example is available in the [Examples App](#examples_app). See example complete [source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/AdjustToContainer/Subviews/ChoiceSelectorView.swift)
@@ -153,7 +157,7 @@ This example shows how easily PinLayout can adjust its layout based on the view'
* Full control: You're in the middle of the layout process, no magic black box.
* Layout one view at a time. Make it simple to code and debug.
* Concise syntax. Layout most views using a single line.
-* [See the complete list here....](docs/PinLayout_principles.md)
+* [**See the complete list here....**](docs/PinLayout_principles.md)
# PinLayout's Performance
@@ -162,11 +166,11 @@ PinLayout's performance has been measured using the [Layout Framework Benchmark]
As you can see in the following chart, PinLayout are faster or equal to manual layouting, and **between 8x and 12x faster than auto layout**, and this for all types of iPhone (5S/6/6S/7/8/X)
-[See here for more details, results and explanation of the benchmark](docs/Benchmark.md).
+#### [See here for more details, results and explanation of the benchmark](docs/Benchmark.md).
@@ -176,75 +180,92 @@ As you can see in the following chart, PinLayout are faster or equal to manual l
### UIKit safeAreaInsets support
PinLayout can easily handle iOS 11 `UIView.safeAreaInsets`, but it goes even further by supporting safeAreaInsets for previous iOS releases (including iOS 7/8/9/10) by adding a property `UIView.pin.safeArea`. [See here for more details](#safeAreaInsets)
-
-
### macOS support
PinLayout support macOS 10.9+.
:pushpin: In this documentation, any methods with parameters of type UIView or UIEdgeInsets are also supported on macOS, using NSView and NSEdgeInsets. See [macOS Support](#macos_support) for more information.
+
### Right to left languages (RTL) support
-PinLayout supports left-to-right (LTR) and right-to-left (RTL) languages. [See here for more details](docs/rtl_support.md).
+PinLayout supports left-to-right (LTR) and right-to-left (RTL) languages.
+#### [See here for more details](docs/rtl_support.md).
+
+
+```swift
+ viewA.pin.top(10).bottom(10).left(10).right(10)
+```
+
+Another shorter possible solution using `all()`:
+
+```swift
+ view.pin.all(10)
+```
+
**Methods**:
-* **`top(:CGFloat)`** / **`top(:Percent)`** / **`top()`** / **`top(:UIEdgeInsets)`**
-The value specifies the top edge distance from the superview's top edge in pixels (or in percentage of its superview's height). `top()` is similar to calling `top(0)`, it position the view top edge directly on its superview top edge. `top(:UIEdgeInsets)` use the `UIEdgeInsets.top` property, is particularly useful with [`UIView.pin.safeArea`](#safeAreaInsets) or `UIView.safeAreaInsets`.
+The following methods are used to position a view’s edge relative to its superview edges.
+
+:pushpin: The offset/margin parameter in the following methods can be either positive and negative. In general cases positive values are used.
+
+* **`top(_ offset: CGFloat)`** / **`top(_ offset: Percent)`** / **`top()`** / **`top(_ margin: UIEdgeInsets)`**
+Position the top edge. The offset specifies the top edge distance from the superview's top edge in pixels (or in percentage of its superview's height). `top()` is similar to calling `top(0)`, it position the view top edge directly on its superview top edge. `top(:UIEdgeInsets)` use the `UIEdgeInsets.top` property, is particularly useful with [safeArea, readable and layout margins](#safeAreaInsets).
+
+* **`bottom(_ offset: CGFloat)`** / **`bottom(_ offset: Percent)`** / **`bottom()`** / **`bottom(_ margin: UIEdgeInsets)`**
+Position the bottom edge. The offset specifies the bottom edge **distance from the superview's bottom edge** in pixels (or in percentage of its superview's height). `bottom()` is similar to calling `bottom(0)`, it position the view bottom edge directly on its superview top edge. `bottom(:UIEdgeInsets)` use the `UIEdgeInsets.bottom` property, it is is particularly useful with [safeArea, readable and layout margins](#safeAreaInsets).
-* **`bottom(:CGFloat)`** / **`bottom(:Percent)`** / **`bottom()`** / **`bottom(:UIEdgeInsets)`**
-The value specifies the bottom edge **distance from the superview's bottom edge** in pixels (or in percentage of its superview's height). `bottom()` is similar to calling `bottom(0)`, it position the view bottom edge directly on its superview top edge. `bottom(:UIEdgeInsets)` use the `UIEdgeInsets.bottom` property, it is is particularly useful with [`UIView.pin.safeArea`](#safeAreaInsets) or `UIView.safeAreaInsets`.
+* **`left(_ offset: CGFloat)`** / **`left(_ offset: Percent)`** / **`left()`** / **`left(_ margin: UIEdgeInsets)`**
+Position the left edge. The offset specifies the left edge distance from the superview's left edge in pixels (or in percentage of its superview's width). `left()` is similar to calling `left(0)`, it position the view left edge directly on its superview left edge. `left(:UIEdgeInsets)` use the `UIEdgeInsets.left` property, it is particularly useful with [safeArea, readable and layout margins](#safeAreaInsets).
-* **`left(:CGFloat)`** / **`left(:Percent)`** / **`left()`** / **`left(:UIEdgeInsets)`**
-The value specifies the left edge distance from the superview's left edge in pixels (or in percentage of its superview's width). `left()` is similar to calling `left(0)`, it position the view left edge directly on its superview left edge. `left(:UIEdgeInsets)` use the `UIEdgeInsets.left` property, it is particularly useful with [`UIView.pin.safeArea`](#safeAreaInsets) or `UIView.safeAreaInsets`.
+* **`right(_ offset: CGFloat)`** / **`right(_ offset: Percent)`** / **`right()`** / **`right(_ margin: UIEdgeInsets)`**
+Position the right edge. The offset specifies the right edge **distance from the superview's right edge** in pixels (or in percentage of its superview's width). `right()` is similar to calling `right(0)`, it position the view right edge directly on its superview right edge. `right(:UIEdgeInsets)` use the `UIEdgeInsets. right` property, it is particularly useful with [safeArea, readable and layout margins](#safeAreaInsets).
-* **`right(:CGFloat)`** / **`right(:Percent)`** / **`right()`** / **`right(:UIEdgeInsets)`**
-The value specifies the right edge **distance from the superview's right edge** in pixels (or in percentage of its superview's width). `right()` is similar to calling `right(0)`, it position the view right edge directly on its superview right edge. `right(:UIEdgeInsets)` use the `UIEdgeInsets. right` property, it is particularly useful with [`UIView.pin.safeArea`](#safeAreaInsets) or `UIView.safeAreaInsets`.
+* **`vCenter(_ offset: CGFloat)`** / **`vCenter(_ offset: Percent)`** / **`vCenter()`**
+Position the vertical center (center.y). The offset specifies the distance vertically of the view's center related to the superview's center in pixels (or in percentage of its superview's height). A positive offset move the view down and a negative value move it up relative to the superview's center. `vCenter()` is similar to calling `vCenter(0)`, it position vertically the view's center directly on its superview vertical center.
-* **`vCenter(:CGFloat)`** / **`vCenter(:Percent)`** / **`vCenter()`**
-The value specifies the distance vertically of the view's center related to the superview's center in pixels (or in percentage of its superview's height). A positive value move the view down and a negative value move it up relative to the superview's center. `vCenter()` is similar to calling `vCenter(0)`, it position vertically the view's center directly on its superview vertical center.
+* **`hCenter(_ offset: CGFloat)`** / **`hCenter(_ offset: Percent)`** / **`hCenter()`**
+Position the horizontal center (center.x). The offset specifies the distance horizontally of the view's center related to the superview's center in pixels (or in percentage of its superview's width). A positive offset move the view to the right and a negative offset move it to the left relative to the superview's center. `hCenter()` is similar to calling `hCenter(0)`, it position horizontally the view's center directly on its superview horizontal center.
-* **`hCenter(:CGFloat)`** / **`hCenter(:Percent)`** / **`hCenter()`**
-The value specifies the distance horizontally of the view's center related to the superview's center in pixels (or in percentage of its superview's width). A positive value move the view to the right and a negative value move it to the left relative to the superview's center. `hCenter()` is similar to calling `hCenter(0)`, it position horizontally the view's center directly on its superview horizontal center.
+##### Methods supporting LTR (left-to-right) and RTL (right-to-left) languages.
-* **`start(:CGFloat)`** / **`start(:Percent)`** / **`start()`** / **`start(:UIEdgeInsets)`** :left_right_arrow:
-In LTR direction the value specifies the left edge distance from the superview's left edge in pixels (or in percentage of its superview's width).
-In RTL direction the value specifies the right edge distance from the superview's right edge in pixels (or in percentage of its superview's width).
-`start()` is similar to calling `start(0)`. `start(:UIEdgeInsets)` use the `UIEdgeInsets.left` property in LTR direction and `UIEdgeInsets.right` in RTL direction, it is particularly useful with [`UIView.pin.safeArea`](#safeAreaInsets) or `UIView.safeAreaInsets`.
+* **`start(_ offset: CGFloat)`** / **`start(_ offset: Percent)`** / **`start()`** / **`start(_ margin: UIEdgeInsets)`** :left_right_arrow:
+Position the left or right edge depending of the LTR language direction. In LTR direction the offset specifies the left edge distance from the superview's left edge in pixels (or in percentage of its superview's width). In RTL direction the offset specifies the right edge distance from the superview's right edge in pixels (or in percentage of its superview's width).
+`start()` is similar to calling `start(0)`. `start(:UIEdgeInsets)` use the `UIEdgeInsets.left` property in LTR direction and `UIEdgeInsets.right` in RTL direction.
-* **`end(:CGFloat)`** / **`end(:Percent)`** / **`end()`** / **`end(:UIEdgeInsets)`** :left_right_arrow:
-In LTR direction the value specifies the right edge distance from the superview's right edge in pixels (or in percentage of its superview's width).
-In RTL direction the value specifies the left edge distance from the superview's left edge in pixels (or in percentage of its superview's width). `end()` is similar to calling `end(0)`. `end(:UIEdgeInsets)` use the `UIEdgeInsets.right` property in LTR direction and `UIEdgeInsets.left` in RTL direction, it is particularly useful with [`UIView.pin.safeArea`](#safeAreaInsets) or `UIView.safeAreaInsets`.
+* **`end(_ offset: CGFloat)`** / **`end(_ offset: Percent)`** / **`end()`** / **`end(_ margin: UIEdgeInsets)`** :left_right_arrow:
+Position the left or right edge depending of the LTR language direction. In LTR direction the offset specifies the right edge distance from the superview's right edge in pixels (or in percentage of its superview's width). In RTL direction the offset specifies the left edge distance from the superview's left edge in pixels (or in percentage of its superview's width). `end()` is similar to calling `end(0)`. `end(:UIEdgeInsets)` use the `UIEdgeInsets.right` property in LTR direction and `UIEdgeInsets.left` in RTL direction.
**Methods pinning multiple edges**:
-* **`all(:CGFloat)`** / **`all(:UIEdgeInsets)`** / **`all()`**
-The value/insets specifies the **top, bottom, left and right edges** distance from the superview's corresponding edge in pixels. Similar to calling `view.top(value).bottom(value).left(value).right(value)`.
+* **`all(_ margin: CGFloat)`** / **`all()`** / **`all(_ margin: UIEdgeInsets)`**
+Position the top, left, bottom and right edges. The margin specifies the **top, bottom, left and right edges** distance from the superview's corresponding edge in pixels. Similar to calling `view.top(value).bottom(value).left(value).right(value)`.
`all()` is similar to calling `all(0)`.
-`all(:UIEdgeInsets)` is particularly useful with [`UIView.pin.safeArea`](#safeAreaInsets) or `UIView.safeAreaInsets`.
+`all(:UIEdgeInsets)` is particularly useful with [safeArea, readable and layout margins](#safeAreaInsets).
-* **`horizontally(:CGFloat)`** / **`horizontally(:Percent)`** /
-**`horizontally(:UIEdgeInsets)`** / **`horizontally()`**
-The value specifies the **left and right edges** on its superview's corresponding edges in pixels (or in percentage of its superview's width).
+* **`horizontally(_ margin: CGFloat)`** / **`horizontally(_ margin: Percent)`** / **`horizontally()`** / **`horizontally(_ margin: UIEdgeInsets)`**
+Position the left and right edges. The margin specifies the **left and right edges** distance from its superview's corresponding edges in pixels (or in percentage of its superview's width).
`horizontally()` is similar to calling `horizontally(0)`.
`horizontally(:UIEdgeInsets)` use the UIEdgeInsets's left and right value to pin left and right edges.
-* **`vertically(:CGFloat)`** / **`vertically(:Percent)`**
-**`vertically(:UIEdgeInsets)`** / **`vertically()`**
-The value specifies the **top and bottom edges** on its superview's corresponding edges in pixels (or in percentage of its superview's height).
+* **`vertically(_ margin: CGFloat)`** / **`vertically(_ margin: Percent)`** / **`vertically()`** / **`vertically(_ margin: UIEdgeInsets)`**
+Position the top and bottom edges. The margin specifies the **top and bottom edges** distance from on its superview's corresponding edges in pixels (or in percentage of its superview's height).
`vertically()` is similar to calling `vertically(0)`.
`vertically(:UIEdgeInsets)` use the UIEdgeInsets's top and bottom value to pin top and bottom edges.
-
###### Usage Examples:
```swift
@@ -259,401 +280,547 @@ The value specifies the **top and bottom edges** on its superview's correspondin
view.pin.top().horizontally() // The view is pinned at the top edge of its parent and fill it horizontally.
```
+
+
###### Example:
-This example layout the view A to fit its superview frame with a margin of 10 pixels. It pins the top, left, bottom and right edges.
+This example position the view’s on the top-right corner of its superview’s topRight and set its size to 100 pixels.
-
+
```swift
- viewA.pin.top(10).bottom(10).left(10).right(10)
+ viewA.pin.topRight().size(100)
```
-Another shorter possible solution using `all()`:
+This is equivalent to:
```swift
- view.pin.all(10)
+ viewA.pin.top().right().size(100)
```
+**Methods:**
-
+* **`center(_ offset: CGFloat)`** / **`center()`**
+Position the horizontal and vertical center (center.y). The offset specifies an offset from the superview's center in pixels. `center()` is similar to calling `center(0)`.
+* **`centerRight(_ rightOffset: CGFloat)`** / **`centerRight()`**
+Position the vertical center (center.y) and the right edge. The offset specifies the right edge distance from the superview's right edge in pixels. `centerRight()` is similar to calling `centerRight(0)`.
-### Layout using edges
-PinLayout has methods to attach a View's edge (top, left, bottom, right, start or end edge) to another view’s edge.
+* **`bottomLeft(_ offset: CGFloat)`** / **`bottomLeft()`**
+Position the bottom and left edges. The offset specifies the distance from their superview's corresponding edges in pixels. `bottomLeft()` is similar to calling `bottomLeft(0)`.
+
+* **`bottomCenter(_ bottomOffset: CGFloat)`** / **`bottomCenter()`**
+Position the bottom and horizontal center (center.x). The offset specifies the bottom edge distance from the superview's bottom edge in pixels. `bottomCenter()` is similar to calling `bottomCenter(0)`.
+
+* **`bottomRight(_ offset: CGFloat)`** / **`bottomRight()`**
+Position the bottom and right edges. The offset specifies the distance from their superview's corresponding edges in pixels. `bottomRight()` is similar to calling `bottomRight(0)`.
+
+
+##### Methods supporting LTR (left-to-right) and RTL (right-to-left) languages.
+
+* **`topStart(_ offset: CGFloat)`** / **`topStart()`** :left_right_arrow:
+In LTR direction position the top and left edges.
+In RTL direction position the top and right edges.
+
+* **`topEnd(_ offset: CGFloat)`** / **`topEnd()`** :left_right_arrow:
+In LTR direction position the top and right edges.
+In RTL direction position the top and left edges.
+
+* **`bottomStart(_ offset: CGFloat)`** / **`bottomStart()`** :left_right_arrow:
+In LTR direction position the bottom and left edges.
+In RTL direction position the bottom and right edges.
+
+* **`bottomEnd(_ offset: CGFloat)`** / **`bottomEnd()`** :left_right_arrow:
+In LTR direction position the bottom and right edges.
+In RTL direction position the bottom and left edges.
+
+* **`centerStart(_ offset: CGFloat)`** / **`centerStart()`** :left_right_arrow:
+In LTR direction position the vertical center (center.y) and the left edge.
+In RTL direction position the vertical center (center.y) and the right edge.
+
+* **`centerEnd(_ offset: CGFloat)`** / **`centerEnd()`** :left_right_arrow:
+In LTR direction position the vertical center (center.y) and the right edge.
+In RTL direction position the vertical center (center.y) and the left edge.
+
+
+###### Usage Examples:
+
+```swift
+ // Position a view at the top left corner with a top and left margin of 10 pixels
+ view.pin.topLeft(10)
+
+ // Position the 4 edges with a margin of 10 pixels.
+ view.pin.topLeft(10).bottomRight(10)
+```
+
+
-
```swift
- viewB.pin.left(to: viewA.edge.right)
+ viewC.pin.top().after(of: viewA).before(of: viewB).margin(10)
```
+This is an equivalent solution using [edges](#edge):
-###### Example 2:
-This example center horizontally the view B inside the view A with a top margin of 10 from the same view.
-
+```swift
+ viewC.pin.top().left(to: viewA.edge.right).right(to: viewB.edge.left). margin(10)
+```
+This is also an equivalent solution using [horizontallyBetween()](#layout_between_w_alignment). See section [Layout between other views](#layout_between):
```swift
- aView.pin.top(to: bView.edge.top).hCenter(to: bView.edge.hCenter).marginTop(10)
-```
+ viewC.pin.horizontallyBetween(viewA, and: viewB, aligned: .top).marginHorizontal(10)
+```
+* **`after(of: UIView, aligned: VerticalAlignment)`**:left_right_arrow:
+**`after(of: [UIView], aligned: VerticalAlignment)`**:left_right_arrow:
+In LTR direction the view is positioned at the right of the specified view(s). In RTL direction the view is positioned at the left. One or many relative views can be specified.
+* **`left(of: UIView, aligned: VerticalAlignment)`**
+**`left(of: [UIView], aligned: VerticalAlignment)`**
+Position the view left of the specified view(s) and aligned it using the specified VerticalAlignment. Similar to `before(of:)`. One or many relative views can be specified.
+
+* **`right(of: UIView, aligned: VerticalAlignment)`**
+**`right(of: [UIView], aligned: VerticalAlignment)`**
+Position the view right of the specified view(s) and aligned it using the specified VerticalAlignment. Similar to `after(of:)`. One or many relative views can be specified.
-### Layout using anchors
-PinLayout can use anchors to position view’s related to other views.
+**`HorizontalAlignment` values:**
-Following methods position the corresponding view anchor on another view’s anchor.
+* **`.left`**: The view's left edge will be left-aligned with the relative view (or the left most view if a list of relative views is specified).
+* **`.center`**: The view's will be horizontally centered with the relative view (or the average hCenter if a list of relative views is used).
+* **`.right`**: The view's right edge will be right-aligned with the relative view (or the right most view if a list of relative views is specified).
+* **`.start`**:left_right_arrow::
+In LTR direction, similar to using `.left`.
+In RTL direction, similar to using `.right`.
+* **`.end`**:left_right_arrow::
+In LTR direction, similar to using `.right`.
+In RTL direction, similar to using `.left`.
-**Methods:**
+**`VerticalAlignment` values:**
-* `topLeft(to anchor: Anchor)`
-* `topCenter(to anchor: Anchor)`
-* `topRight(to anchor: Anchor)`
-* `topStart(to anchor: Anchor)`:left_right_arrow:
-* `topEnd(to anchor: Anchor)`:left_right_arrow:
-* `centerLeft(to anchor: Anchor)`
-* `center(to anchor: Anchor)`
-* `centerRight(to anchor: Anchor)`
-* `centerStart(to anchor: Anchor)`:left_right_arrow:
-* `centerEnd(to anchor: Anchor)`:left_right_arrow:
-* `bottomLeft(to anchor: Anchor)`
-* `bottomCenter(to anchor: Anchor)`
-* `bottomRight(to anchor: Anchor)`
-* `bottomStart(to anchor: Anchor)`:left_right_arrow:
-* `bottomEnd(to anchor: Anchor)`:left_right_arrow:
+* **`.top`**: The view's top edge will be top-aligned with the relative view (or the top most view if a list of relative views is specified).
+* **`.center`**: The view's will be vertically centered with the relative view (or the average vCenter if a list of relative views is used).
+* **`.bottom`**: The view's bottom edge will be bottom-aligned with the relative view (or the bottom most view if a list of relative views is specified).
-:pushpin: These methods can pin a view’s anchor to any other view's anchor, even if don't have the same direct superview! It works with any views that have at some point the same ancestor.
+:pushpin: **Multiple relative views**: If for example a call to `below(of: [...], aligned:) specify multiple relative views, the view will be layouted below *ALL* these views. The alignment will be applied using all relative views.
+
+:pushpin: These methods can layout a view’s relative to any views, even if they don't have the same direct superview/parent! It works with any views that have a shared ancestor.
###### Usage examples:
```swift
- view.pin.topCenter(to: view1.anchor.bottomCenter)
- view.pin.topLeft(to: view1.anchor.topLeft).bottomRight(to: view1.anchor.center)
+ view.pin.above(of: view2, aligned: .left)
+ view.pin.below(of: [view2, view3, view4], aligned: .left)
+ view.pin.after(of: view2, aligned: .top).before(of: view3, aligned: .bottom)
```
###### Example:
+The following example layout the view B below the view A aligned on its center.
-Layout using an anchor. This example pins the view B topLeft anchor on the view A topRight anchor.
-
-
+
```swift
- viewB.pin.topLeft(to: viewA.anchor.topRight)
-```
+ viewB.pin.below(of: viewA, aligned: .center)
+```
+This is an equivalent solution using anchors:
-
-
+```swift
+ a.pin.below(of: [imageView, label], aligned: .left).right(to: label.edge.right).marginTop(10)
+```
+This is an equivalent solutions using other methods:
```swift
- viewC.pin.topLeft(to: viewA.anchor.topRight)
- .bottomRight(to: viewB.anchor.bottomLeft).marginHorizontal(10)
+ let maxY = max(imageView.frame.maxY, label.frame.maxY) // Not so nice
+ a.pin.top(maxY).left(to: imageView.edge.left).right(to: label.edge.right).marginTop(10)
+```
+
+### Positioning using only visible relative Views
+
+All PinLayout's relative methods can accept an array of Views (ex: `below(of: [UIView])`). Using these methods its possible to filter the list of relative Views before the list is used by PinLayout.
+
+You can define your own filter methods, but PinLayout has a filter method called `visible` that can be used to layout a view related to only visible views. This can be really useful when some views may be visible or hidden depending on the situation.
+
+```swift
+ view.pin.below(of: visible([ageSwitch, ageField])).horizontally().
```
+Note that the **Form** example use this filter method, see [Examples App](#examples_app).
+
+
```swift
- viewA.pin.topRight()
-```
+ view.pin.horizontallyBetween(viewA, and: viewB).top(10).marginHorizontal(5)
+```
-This is equivalent to:
+Note that the same result can also be achieved using an alignment parameter, describe in the [next section](#layout_between_w_alignment):
```swift
- viewA.pin.topRight(to: superview.anchor.topRight)
- // OR
- viewA.pin.top().right()
+ view.pin.horizontallyBetween(viewA, and: viewB, aligned: .top).marginHorizontal(5)
```
-
+
-```swift
- viewC.pin.top().after(of: viewA).before(of: viewB).margin(10)
-```
-This is an equivalent solution using [edges](#edge):
```swift
- viewC.pin.top().left(to: viewA.edge.right).right(to: viewB.edge.left).margin(10)
+ view.pin.verticallyBetween(viewA, and: viewB, aligned: .center).marginVertical(10)
```
-This is also an equivalent solution using [relative positioning and alignment](#relative_positioning_w_alignment) explained in the next section:
+
-**Methods:**
-* **`above(of: UIView, aligned: HorizontalAlignment)`**
-**`above(of: [UIView], aligned: HorizontalAlignment)`**
-Position the view above the specified view(s) and aligned it using the specified HorizontalAlignment. One or many relative views can be specified. This method is similar to pinning one view’s anchor: bottomLeft, bottomCenter or bottomRight.
-
-* **`below(of: UIView, aligned: HorizontalAlignment)`**
-**`below(of: [UIView], aligned: HorizontalAlignment)`**
-Position the view below the specified view(s) and aligned it using the specified HorizontalAlignment. One or many relative views can be specified. This method is similar to pinning one view’s anchor: topLeft, topCenter or topRight.
-
-* **`before(of: UIView, aligned: HorizontalAlignment)`**:left_right_arrow:
-**`before(of: [UIView], aligned: HorizontalAlignment)`**:left_right_arrow:
-In LTR direction the view is positioned at the left of the specified view(s). In RTL direction the view is positioned at the right. One or many relative views can be specified.
+### Layout using edges
-* **`after(of: UIView, aligned: HorizontalAlignment)`**:left_right_arrow:
-**`after(of: [UIView], aligned: HorizontalAlignment)`**:left_right_arrow:
-In LTR direction the view is positioned at the right of the specified view(s). In RTL direction the view is positioned at the left. One or many relative views can be specified.
+PinLayout has methods to attach a View's edge (top, left, bottom, right, start or end edge) to another view’s edge.
-* **`left(of: UIView, aligned: VerticalAlignment)`**
-**`left(of: [UIView], aligned: HorizontalAlignment)`**
-Position the view left of the specified view(s) and aligned it using the specified VerticalAlignment. Similar to `before(of:)`. One or many relative views can be specified. This method is similar to pinning one view’s anchor: topRight, centerRight or bottomRight.
-
-* **`right(of: UIView, aligned: VerticalAlignment)`**
-**`right(of: [UIView], aligned: HorizontalAlignment)`**
-Position the view right of the specified view(s) and aligned it using the specified VerticalAlignment. Similar to `after(of:)`. One or many relative views can be specified. This method is similar to pinning one view’s anchor: topLeft, centerLeft or bottomLeft.
+**Methods:**
+
+* **`top(to edge: ViewEdge)`**:
+Position the view's top edge directly on another view’s edge (top/vCenter/bottom).
+* **`vCenter(to edge: ViewEdge)`**:
+Position vertically the view's center directly on another view’s edge (top/vCenter/bottom).
-**How alignment is applied:**
+* **`bottom(to edge: ViewEdge)`**:
+Position the view's bottom edge directly on another view’s edge (top/vCenter/bottom).
-* **`HorizontalAlignment.left`**: The view's left edge will be aligned to the left most relative view.
-* **`HorizontalAlignment.center`**: The view's hCenter edge will be aligned with the average hCenter of all relative views.
-* **`HorizontalAlignment.right`**: The view's right edge will be aligned to the right most relative view.
-* **`HorizontalAlignment.start`**:left_right_arrow::
-In LTR direction the view's left edge will be aligned to the left most relative view.
-In RTL direction the view's right edge will be aligned to the right most relative view.
-* **`HorizontalAlignment.end`**:left_right_arrow::
-In LTR direction the view's right edge will be aligned to the right most relative view.
-In RTL direction the view's left edge will be aligned to the right most relative view.
-* **`VerticalAlignment.top`**: The view's top edge will be aligned to the top most relative view.
-* **`VerticalAlignment.center`**: The view's vCenter edge will be aligned with the average vCenter of all relative views.
-* **`VerticalAlignment.bottom`**: The view's bottom edge will be aligned to the bottom most relative view.
+* **`left(to: edge: ViewEdge)`**:
+Position the view's left edge directly on another view’s edge (left/hCenter/right).
-:pushpin: **Multiple relative views**: If for example a call to `below(of: [...], aligned:) specify multiple relative views, the view will be layouted below *ALL* these views. The alignment will be applied using all relative view
+* **`hCenter(to: edge: ViewEdge)`**:
+Position horizontally the view's center directly on another view’s edge (left/hCenter/right).
-:pushpin: These methods **set the position of a view's anchor**: topLeft, topCenter, topRight, centerLeft, .... For example `below(of ..., aligned: .right)` set the view's topRight anchor, `right(of ..., aligned: .center) set the view's centerLeft anchor, ...
+* **`right(to: edge: ViewEdge)`**:
+Position the view's right edge directly on another view’s edge (left/hCenter/right).
-:pushpin: These methods **set the position of a view's edge**: top, left, bottom or right. For example `below(of ...)` set the view's top edge, `right(of ...) set the view's left edge, ...
+* **`start(to: edge: ViewEdge)`**:left_right_arrow:
+In LTR direction it position the view's left edge directly on another view’s edge.
+In RTL direction it position the view's right edge directly on another view’s edge.
+
+* **`end(to: edge: ViewEdge)`**:left_right_arrow:
+In LTR direction it position the view's top edge directly on another view’s edge.
+In RTL direction it position the view's bottom edge directly on another view’s edge.
+:pushpin: These methods can pin a view’s edge to any other view's edge, even if they don't have the same direct superview! It works with any views that have a shared ancestor.
###### Usage examples:
```swift
- view.pin.above(of: view2, aligned: .left)
- view.pin.below(of: [view2, view3, view4], aligned: .left)
- view.pin.after(of: view2, aligned: .top).before(of: view3, aligned: .bottom)
+ view.pin.left(to: view1.edge.right)
+ view.pin.left(to: view1.edge.right).top(to: view2.edge.right)
```
-###### Example:
-The following example layout the view B below the view A aligned on its center.
+###### Example 1:
+This example layout the view B left edge on the view A right edge. It only changes the view B left coordinate.
-
+
+```swift
+ viewB.pin.left(to: viewA.edge.right)
+```
+
+###### Example 2:
+This example center horizontally the view B inside the view A with a top margin of 10 from the same view.
+
+
+
+```swift
+ aView.pin.top(to: bView.edge.top).hCenter(to: bView.edge.hCenter).marginTop(10)
+```
+
+
+
+
+### Layout using anchors
+
+PinLayout can use anchors to position view’s related to other views.
+
+Following methods position the corresponding view anchor on another view’s anchor.
+
+**Methods:**
+
+* `topLeft(to anchor: Anchor)`
+* `topCenter(to anchor: Anchor)`
+* `topRight(to anchor: Anchor)`
+* `topStart(to anchor: Anchor)`:left_right_arrow:
+* `topEnd(to anchor: Anchor)`:left_right_arrow:
+* `centerLeft(to anchor: Anchor)`
+* `center(to anchor: Anchor)`
+* `centerRight(to anchor: Anchor)`
+* `centerStart(to anchor: Anchor)`:left_right_arrow:
+* `centerEnd(to anchor: Anchor)`:left_right_arrow:
+* `bottomLeft(to anchor: Anchor)`
+* `bottomCenter(to anchor: Anchor)`
+* `bottomRight(to anchor: Anchor)`
+* `bottomStart(to anchor: Anchor)`:left_right_arrow:
+* `bottomEnd(to anchor: Anchor)`:left_right_arrow:
-```swift
- viewB.pin.below(of: viewA, aligned: .center)
-```
-This is an equivalent solution using anchors:
+:pushpin: These methods can pin a view’s anchor to any other view's anchor, even if they don't have the same direct superview! It works with any views that have a shared ancestor.
+###### Usage examples:
```swift
- viewB.pin.topCenter(to: viewA.anchor.bottomCenter)
+ view.pin.topCenter(to: view1.anchor.bottomCenter)
+ view.pin.topLeft(to: view1.anchor.topLeft).bottomRight(to: view1.anchor.center)
```
-###### Example:
-The following example layout the view A **below the UIImageView and the UILabel**.
-View A should be left aligned to the UIImageView and right aligned to the UILabel, with a top margin of 10 pixels.
+###### Example 1:
-
+Layout using an anchor. This example pins the view B topLeft anchor on the view A topRight anchor.
+
-```swift
- a.pin.below(of: [imageView, label], aligned: .left).right(to: label.edge.right).marginTop(10)
-```
-This is an equivalent solutions using other methods:
```swift
- let maxY = max(imageView.frame.maxY, label.frame.maxY) // Not so nice
- a.pin.top(maxY).left(to: imageView.edge.left).right(to: label.edge.right).marginTop(10)
-```
+ viewB.pin.topLeft(to: viewA.anchor.topRight)
+```
-
-All PinLayout's relative methods can accept an array of Views (ex: `below(of: [UIView])`). Using these methods its possible to filter the list of relative Views before the list is used by PinLayout.
-PinLayout has a filter method called `visible` that can be used to layout a view related to only visible views. This can be really useful when some views may be visible or hidden depending on the situation.
+```swift
+ viewB.pin.center(to: viewA.anchor.topRight)
+```
-###### Example:
-The following example contains a UISwitch. Below a UITextField that is visible only when the UISwitch is set to ON. And then follow another UITextField. This example use the `visible(views: [UIView]) -> [UIView]` filter method that returns only views with `UIView.isHidden` set to false or `UIView.alpha` greater than 0.
+###### Example 3:
-
+Layout using multiple anchors. It is also possible to combine two anchors to pin the position and the size of a view. The following example will position the view C between the view A and B with horizontal margins of 10px.
+
```swift
- formTitleLabel.pin.topCenter().marginTop(margin)
- nameField.pin.below(of: formTitleLabel).horizontally().height(40).margin(margin)
-
- ageSwitch.pin.below(of: nameField).horizontally().height(40).margin(margin)
- ageField.pin.below(of: ageSwitch).horizontally().height(40).margin(margin)
-
- // Layout the Address UITextField below the last visible view, either ageSwitch or ageField.
- addressField.pin.below(of: visibles([ageSwitch, ageField])).horizontally().height(40).margin(margin)
+ viewC.pin.topLeft(to: viewA.anchor.topRight)
+ .bottomRight(to: viewB.anchor.bottomLeft).marginHorizontal(10)
```
-Note that this example is extracted from the **Form** example, see [Examples App](#examples_app)
+This is an another possible solution using [horizontallyBetween()](#layout_between_w_alignment):
+
+```swift
+ viewC.pin.horizontallyBetween(viewA, and: viewB, aligned: .top).height(of: viewA).marginHorizontal(10)
+```
-
-
-```swift
- imageView.pin.top().hCenter().width(50%).aspectRatio()
-```
-
-
-
-
## Margins
@@ -890,7 +1022,7 @@ Set the top and bottom margins to the specified value.
* **`margin(:CGFloat)`** / **`margin(: Percent)`**
Apply the value to all margins (top, left, bottom, right), in pixels or in percentage of its superview's width/height.
* **`margin(:UIEdgeInsets)`**
-Set all margins using an UIEdgeInsets. This method is particularly useful to set all margins using iOS 11 with `UIView.safeAreaInsets` or [`UIView.pin.safeArea`](#safeAreaInsets).
+Set all margins using an UIEdgeInsets. This method is particularly useful to set all margins using [safeArea, readable and layout margins](#safeAreaInsets).
* **`margin(_ insets: NSDirectionalEdgeInsets) `**
Set all margins using an NSDirectionalEdgeInsets. This method is useful to set all margins using iOS 11 `UIView. directionalLayoutMargins` when layouting a view supporting RTL/LTR languages.
* **`margin(_ vertical: CGFloat, _ horizontal: CGFloat)`**
@@ -1036,8 +1168,67 @@ NOTE: In that in that particular situation, the same results could have been ach
+
+
+## Aspect Ratio
+Set the view aspect ratio.
+AspectRatio solves the problem of knowing one dimension of an element and an aspect ratio, this is particularly useful for images.
+
+AspectRatio is applied only if a single dimension (either width or height) can be determined, in that case the aspect ratio will be used to compute the other dimension.
+
+* AspectRatio is defined as the ratio between the width and the height (width / height).
+* An aspect ratio of 2 means the width is twice the size of the height.
+* AspectRatio respects the min (minWidth/minHeight) and the max (maxWidth/maxHeight)
+ dimensions of an item.
+
+**Methods:**
+
+* **`aspectRatio(_ ratio: CGFloat)`**:
+Set the view aspect ratio using a CGFloat. AspectRatio is defined as the ratio between the width and the height (width / height).
+
+* **`aspectRatio(of view: UIView)`**:
+Set the view aspect ratio using another UIView's aspect ratio.
+
+* **`aspectRatio()`**:
+If the layouted view is an UIImageView, this method will set the aspectRatio using the UIImageView's image dimension. For other types of views, this method as no impact.
+
+###### Usage examples:
+```swift
+ aView.pin.left().width(100%).aspectRatio(2)
+ imageView.pin.left().width(200).aspectRatio()
+```
+
+###### Example:
+This example layout an UIImageView at the top and center it horizontally, it also adjust its width to 50%. The view’s height will be adjusted automatically using the image aspect ratio.
+
+
+
+
+```swift
+ imageView.pin.top().hCenter().width(50%).aspectRatio()
+```
+
+
+
+
-## UIKit safeAreaInsets support
+## safeArea, readable, layout and keyboard margins
+
+UIKit expose 4 kind of areas/guides that can be used to layout views.
+PinLayout expose them using these properties:
+
+1. **`UIView.pin.safeArea`**: Expose UIKit `UIView.safeAreaInsets` / `UIView.safeAreaLayoutGuide`.
+2. **`UIView.pin.readableMargins`**: Expose UIKit `UIView.readableContentGuide`.
+3. **`UIView.pin.layoutMargins`**: Expose UIKit `UIView.layoutMargins` / `UIView.layoutMarginsGuide`.
+4. **`UIView.pin.keyboardArea`**: Expose UIKit `UIView.keyboardLayoutGuide`. [iOS 15+]
+
+The following image display the 3 areas on an iPad in landscape mode. (safeArea, readableMargins, layoutMargins)
+
+
+
+See the **SafeArea & readableMargins** example in the [Examples App](#examples_app).
+
+### 1. pin.safeArea
PinLayout can handle easily iOS 11 `UIView.safeAreaInsets`, but it goes further by supporting safeAreaInsets for previous iOS releases (including iOS 7/8/9/10) by adding a property `UIView.pin.safeArea`. PinLayout also extends the support of `UIView.safeAreaInsetsDidChange()` callback on iOS 7/8/9/10.
@@ -1063,8 +1254,6 @@ The safe area of a view represent the area not covered by navigation bars, tab b
button.pin.top(view.pin.safeArea)
```
-
-
##### UIView.safeAreaInsetsDidChange():
* iOS 11 has also introduced the method [`UIView.safeAreaInsetsDidChange()`](https://developer.apple.com/documentation/uikit/uiview/2891104-safeareainsetsdidchange) which is called when the safe area of the view changes. This method is called only when your app runs on a iOS 11 device. **PinLayout's extend that and support this method also on older iOS releases including iOS 9/10**.
@@ -1111,8 +1300,6 @@ The safe area of a view represent the area not covered by navigation bars, tab b
}
```
* **disable**: In this mode PinLayout won't call `UIView.safeAreaInsetsDidChange` on iOS 8/9/10. Note that this is the default mode on iOS 8.
-
-
+
+| Source code | Result | Description |
+|---------------------|----------|-------------------|
+| `view.pin.wrapContent()` |
| Adjust the view's height and width to tight fit its subviews. |
+| `view.pin.wrapContent(padding: 10)` |
| Adjust the view's height and width and add a padding of 10 pixels around its subviews. |
+| `view.pin.wrapContent(.horizontally)` |
| Adjust only the view's width. |
+| `view.pin.wrapContent(.vertically)` |
| Adjust only the view's height. |
+
+
+###### Example:
+This example shows how a view (`containerView`) that has subviews (`imageView` and `label`) can be adjusted to the size of its subviews and then centered inside its parent.
+
+
+
+```swift
+ label.pin.below(of: imageView, aligned: .center).marginTop(4)
+ containerView.pin.wrapContent(padding: 10).center()
+```
+* Line 1: Position the label below the imageView aligned on its center with a top margin of 4 pixels.
+* Line 2: Adjust the `containerView`'s size and position its subviews to create a tight wrap around them with a padding of 10 pixels all around. The `containerView` is also centered inside its parent (superview).
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
+
See [Layout Framework Benchmark](https://github.com/layoutBox/LayoutFrameworkBenchmark) for complete details and benchmarks charts for iPhone X/8/7/6S/...
@@ -55,30 +56,29 @@ override func layoutSubviews() {
super.layoutSubviews()
let hMargin: CGFloat = 8
- let vMargin: CGFloat = 2
+ let vMargin: CGFloat = 4
optionsLabel.pin.topRight().margin(hMargin)
actionLabel.pin.topLeft().margin(hMargin)
posterImageView.pin.below(of: actionLabel, aligned: .left).marginTop(10)
- posterNameLabel.pin.right(of: posterImageView, aligned: .top).margin(-6, 6).right(hMargin).sizeToFit()
- posterHeadlineLabel.pin.below(of: posterNameLabel, aligned: .left).right(hMargin).marginTop(1).sizeToFit()
- posterTimeLabel.pin.below(of: posterHeadlineLabel, aligned: .left).right(hMargin).marginTop(1).sizeToFit()
- posterCommentLabel.pin.below(of: posterTimeLabel).left(hMargin).right().right(hMargin)
- .marginTop(vMargin).sizeToFit()
+ posterHeadlineLabel.pin.after(of: posterImageView, aligned: .center).marginLeft(4)
+ posterNameLabel.pin.above(of: posterHeadlineLabel, aligned: .left).marginBottom(vMargin)
+ posterTimeLabel.pin.below(of: posterHeadlineLabel, aligned: .left).marginTop(vMargin)
- contentImageView.pin.below(of: posterCommentLabel).hCenter().width(100%).sizeToFit()
- contentTitleLabel.pin.below(of: contentImageView).left().right().marginHorizontal(hMargin).sizeToFit()
- contentDomainLabel.pin.below(of: contentTitleLabel, aligned: .left).right().marginRight(hMargin)
- .sizeToFit()
+ posterCommentLabel.pin.below(of: posterTimeLabel).left(hMargin).marginTop(vMargin)
+
+ contentImageView.pin.below(of: posterCommentLabel, aligned: .left).right().marginTop(vMargin).marginRight(hMargin)
+ contentTitleLabel.pin.below(of: contentImageView).left().marginHorizontal(hMargin)
+ contentDomainLabel.pin.below(of: contentTitleLabel, aligned: .left)
likeLabel.pin.below(of: contentDomainLabel, aligned: .left).marginTop(vMargin)
- commentLabel.pin.top(to: likeLabel.edge.top).hCenter(50%)
+ commentLabel.pin.top(to: likeLabel.edge.top).hCenter()
shareLabel.pin.top(to: likeLabel.edge.top).right().marginRight(hMargin)
actorImageView.pin.below(of: likeLabel, aligned: .left).marginTop(vMargin)
- actorCommentLabel.pin.right(of: actorImageView, aligned: .center).marginLeft(4)
+ actorCommentLabel.pin.after(of: actorImageView, aligned: .center).marginLeft(4)
}
```
diff --git a/docs/Benchmark/benchmark_comparison_all.png b/docs/Benchmark/benchmark_comparison_all.png
deleted file mode 100644
index 7b6068e1..00000000
Binary files a/docs/Benchmark/benchmark_comparison_all.png and /dev/null differ
diff --git a/docs/Benchmark/benchmark_comparison_all_small.png b/docs/Benchmark/benchmark_comparison_all_small.png
index fbd2baf4..0e93d47e 100644
Binary files a/docs/Benchmark/benchmark_comparison_all_small.png and b/docs/Benchmark/benchmark_comparison_all_small.png differ
diff --git a/docs/Benchmark/benchmark_result_Autolayout.png b/docs/Benchmark/benchmark_result_Autolayout.png
deleted file mode 100644
index 016b9ce1..00000000
Binary files a/docs/Benchmark/benchmark_result_Autolayout.png and /dev/null differ
diff --git a/docs/Benchmark/benchmark_result_FlexLayout.png b/docs/Benchmark/benchmark_result_FlexLayout.png
deleted file mode 100644
index b22f4233..00000000
Binary files a/docs/Benchmark/benchmark_result_FlexLayout.png and /dev/null differ
diff --git a/docs/Benchmark/benchmark_result_LayoutKit.png b/docs/Benchmark/benchmark_result_LayoutKit.png
deleted file mode 100644
index 1e0e3ca1..00000000
Binary files a/docs/Benchmark/benchmark_result_LayoutKit.png and /dev/null differ
diff --git a/docs/Benchmark/benchmark_result_PinLayout.png b/docs/Benchmark/benchmark_result_PinLayout.png
deleted file mode 100644
index 6fe1fd09..00000000
Binary files a/docs/Benchmark/benchmark_result_PinLayout.png and /dev/null differ
diff --git a/docs/PinLayout_principles.md b/docs/PinLayout_principles.md
index 34664e37..3ee6b36b 100644
--- a/docs/PinLayout_principles.md
+++ b/docs/PinLayout_principles.md
@@ -6,7 +6,7 @@
* Manual layouting (doesn't rely on auto layout).
-* PinLayout exist to be simple and fast as possible! In fact, it is fast as manual layouting. See [performance results below.](#performance)
+* PinLayout exist to be simple and fast as possible! In fact, it is fast as manual layouting. See [performance results here.](https://github.com/layoutBox/PinLayout#pinlayouts-performance)
* Full control: You're in the middle of the layout process, no magic black box.
* You can add conditions (if/switch/guard/...) related to the device orientation, device type, traitCollection, animations, ...
@@ -31,4 +31,4 @@ Each view can use the layout system that better suit it (PinLayout, autolayout,
* Not too intrusive. PinLayout only adds three properties to existing iOS classes: `UIView.pin`, `UIView.anchor` and `UIView.edge`
* Minimize as much as possible calculations and constants when layouting views. But it is always possible to add advanced computation if required.
-* Method's name match as much as possible other layout frameworks, including [FlexLayout](https://github.com/layoutBox/FlexLayout)/flexbox, CSS, React Native, …
\ No newline at end of file
+* Method's name match as much as possible other layout frameworks, including [FlexLayout](https://github.com/layoutBox/FlexLayout)/flexbox, CSS, React Native, …
diff --git a/docs/animations.md b/docs/animations.md
new file mode 100644
index 00000000..dbb738b2
--- /dev/null
+++ b/docs/animations.md
@@ -0,0 +1,190 @@
+
+
+
+
+Note that in the following source code the view's size was set to 150 px (`view.pin.size(150)`) in the initialization.
+
+
+### Basic strategy: Using `UIView.setNeedsLayout` and `UIView.layoutIfNeeded`
+In this strategy, to force a call to layoutSubviews(), we call `UIView.setNeedsLayout` and `UIView.layoutIfNeeded` from the animation block.
+
+```swift
+var isViewLeftDocked = true
+
+override func layoutSubviews() {
+ super.layoutSubviews()
+
+ if isViewLeftDocked {
+ view.pin.top().left()
+ } else {
+ view.pin.top().right()
+ }
+}
+
+func didTapTogglePosition() {
+ isViewLeftDocked = !isViewLeftDocked
+
+ UIView.animate(withDuration: 0.3) {
+ self.setNeedsLayout()
+ self.layoutIfNeeded()
+ }
+}
+```
+
+### Using a layout method
+This strategy use a private method to layout the animated view (`layoutAnimatedView()`). The advantage of this solution is that it is not required to call `UIView.setNeedsLayout` and `UIView.layoutIfNeeded` to relayout the view.
+
+```swift
+var isViewLeftDocked = true
+
+override func layoutSubviews() {
+ super.layoutSubviews()
+
+ layoutAnimatedView()
+}
+
+private func layoutAnimatedView() {
+ if isViewLeftDocked {
+ view.pin.top().left()
+ } else {
+ view.pin.top().right()
+ }
+}
+
+func didTapTogglePosition() {
+ isViewLeftDocked = !isViewLeftDocked
+
+ UIView.animate(withDuration: 0.3) {
+ self.layoutAnimatedView()
+ }
+}
+```
+
+### Using an animation state
+This strategy is similar to the previous one, but use an enumeration to keep the animation state.
+
+```swift
+enum AnimationState {
+ case leftDocked
+ case rightDocked
+}
+
+var animationState = AnimationState.leftDocked
+
+override func layoutSubviews() {
+ super.layoutSubviews()
+
+ layoutAnimatedView()
+}
+
+private func layoutAnimatedView() {
+ switch animationState {
+ case .leftDocked:
+ view.pin.top().left()
+ case .rightDocked:
+ view.pin.top().right()
+ }
+}
+
+func didTapTogglePosition() {
+ switch animationState {
+ case .leftDocked: animationState = .rightDocked
+ case .rightDocked: animationState = .leftDocked
+ }
+
+ UIView.animate(withDuration: 0.3) {
+ self.layoutAnimatedView()
+ }
+}
+```
+
+### Other strategies
+It's really up to you to think of animation's strategies that match your situation. With PinLayout you are always in control of everything, including animations.
+
+
+
+## Collision between animations and `layoutSubViews()`
+In some particular situation it is possible that `layoutSubViews()` may be called during the animation is in progress, this can occur particularly on long animation. To handle this kind of situation it is possible to use a boolean indicating if an animation is in progress, and to block temporarely the layout of animated views in `layoutSubViews()`.
+
+Here is an example:
+
+```swift
+enum AnimationState {
+ case leftDocked
+ case rightDocked
+}
+
+var animationState = AnimationState.leftDocked
+var isAnimating = false
+
+override func layoutSubviews() {
+ super.layoutSubviews()
+
+ // If an animation of the view is in progress, we don't update animated views position.
+ guard !isAnimating else { return }
+ layoutAnimatedView()
+}
+
+private func layoutAnimatedView() {
+ switch animationState {
+ case .leftDocked:
+ view.pin.top().left()
+ case .rightDocked:
+ view.pin.top().right()
+ }
+}
+
+func didTapTogglePosition() {
+ switch animationState {
+ case .leftDocked: animationState = .rightDocked
+ case .rightDocked: animationState = .leftDocked
+ }
+
+ UIView.animate(withDuration: 0.3, animations: {
+ self.isAnimating = true
+ self.layoutAnimatedView()
+ }, completion: { (_) in
+ self.isAnimating = false
+ })
+}
+```
+
+
+
+## Animation Example
+You can check the animation example available in the [PinLayout's Example App](https://github.com/layoutBox/PinLayout/blob/master/docs/examples.md):
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/Animations/AnimationsView.swift)
+
+
+
+
diff --git a/docs/examples.md b/docs/examples.md
new file mode 100644
index 00000000..894bff63
--- /dev/null
+++ b/docs/examples.md
@@ -0,0 +1,127 @@
+
+
+
+
+## Relative Edges Layout Example
+Example showing how to layout views relative to other views.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/RelativeView/RelativeView.swift)
+
+
+
+## Between Example
+Example showing how to use [`horizontallyBetween()`](https://github.com/layoutBox/PinLayout#layout-between-other-views) to position a view between two other views.
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/BetweenView/BetweenView.swift)
+
+
+
+## UITableView Example
+Example using a UITableView with variable height cells.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/TableViewExample/TableViewExampleView.swift)
+
+
+
+
+## UITableView Example with cells using `pin.readableMargins`
+Similar to the UITableView Example, but in this one cells use `pin.readableMargins` to layout their content inside the zone defined by `UIView.readableContentGuide`.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/TableViewExample/TableViewExampleView.swift)
+
+
+
+
+## UICollectionView Example
+Example using a UICollectionView with variable height cells.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/CollectionViewExample/HouseCell.swift)
+
+
+
+## Animations Example
+Example showing how to animate views with PinLayout.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/Animations/AnimationsView.swift)
+
+
+
+## Right to left language support Example
+This example show how PinLayout can support simultaneously Left to right and right to left languages.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/IntroRTL/IntroRTLView.swift)
+
+
+
+
+## pin.safeArea example
+Example showing the usage of `UIView.pin.safeArea`] with UINavigationController and UITabViewController:
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/SafeArea/SafeAreaView.swift)
+
+
+
+Also display the usage of `pin.readableMargins` and `pin.layoutMargins`:
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/SafeArea/SafeAreaAndMarginsView.swift)
+
+
+
+
+## Adjust To Container Example
+Example showing how PinLayout can be used to adjust the layout depending of the space available.
+
+In this example the UISegmentedControl is shown below its label if the available width is smaller than 500 pixels, or on the same line as the label if the width is wider.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/AdjustToContainer/Subviews/ChoiceSelectorView.swift)
+
+
+
+
+## wrapContent Example
+This example show how to use the `wrapContent()` method. This method is particularly useful to wrap a group of views and center them.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/WrapContent/WrapContentView.swift)
+
+
+
+## Form Example
+This example is a basic form containing 4 fields.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/Form/FormView.swift)
+
+
+
+## Auto Adjusting Size Example
+This example show how fixed size views and expandable views can be layouted using PinLayout to fill the available space.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/AutoAdjustingSize/AutoAdjustingSizeView.swift)
+
+
+
+
+## Automatic Sizing Example
+This example show how to use Automatic Sizing (`autoSizeThatFits()`) to compute views size.
+[Source code](https://github.com/layoutBox/PinLayout/tree/master/Example/PinLayoutSample/UI/Examples/AutoSizing)
+
+
diff --git a/docs/images/example-animations-large.gif b/docs/images/example-animations-large.gif
new file mode 100644
index 00000000..3451d365
Binary files /dev/null and b/docs/images/example-animations-large.gif differ
diff --git a/docs/images/example-animations.gif b/docs/images/example-animations.gif
new file mode 100644
index 00000000..beb2dbfb
Binary files /dev/null and b/docs/images/example-animations.gif differ
diff --git a/docs/images/pinlayout_animation_example1.gif b/docs/images/pinlayout_animation_example1.gif
new file mode 100644
index 00000000..2e920652
Binary files /dev/null and b/docs/images/pinlayout_animation_example1.gif differ
diff --git a/docs/images/pinlayout_example_anchor_center.png b/docs/images/pinlayout_example_anchor_center.png
new file mode 100644
index 00000000..73d24fbc
Binary files /dev/null and b/docs/images/pinlayout_example_anchor_center.png differ
diff --git a/docs/images/pinlayout_example_layout_margins_all.png b/docs/images/pinlayout_example_layout_margins_all.png
new file mode 100644
index 00000000..703eb4eb
Binary files /dev/null and b/docs/images/pinlayout_example_layout_margins_all.png differ
diff --git a/docs/images/pinlayout_example_layout_margins_landscape.png b/docs/images/pinlayout_example_layout_margins_landscape.png
new file mode 100644
index 00000000..4d29810c
Binary files /dev/null and b/docs/images/pinlayout_example_layout_margins_landscape.png differ
diff --git a/docs/images/pinlayout_example_layout_margins_portrain.png b/docs/images/pinlayout_example_layout_margins_portrain.png
new file mode 100644
index 00000000..11c533d3
Binary files /dev/null and b/docs/images/pinlayout_example_layout_margins_portrain.png differ
diff --git a/docs/images/pinlayout_example_tableview_readable_content_all.png b/docs/images/pinlayout_example_tableview_readable_content_all.png
new file mode 100644
index 00000000..805c74c2
Binary files /dev/null and b/docs/images/pinlayout_example_tableview_readable_content_all.png differ
diff --git a/docs/images/pinlayout_example_tableview_readable_content_landscape.png b/docs/images/pinlayout_example_tableview_readable_content_landscape.png
new file mode 100644
index 00000000..e4cc7be9
Binary files /dev/null and b/docs/images/pinlayout_example_tableview_readable_content_landscape.png differ
diff --git a/docs/images/pinlayout_example_tableview_readable_content_portrait.png b/docs/images/pinlayout_example_tableview_readable_content_portrait.png
new file mode 100644
index 00000000..71ff37aa
Binary files /dev/null and b/docs/images/pinlayout_example_tableview_readable_content_portrait.png differ
diff --git a/docs/images/pinlayout_example_topRight.png b/docs/images/pinlayout_example_topRight.png
new file mode 100644
index 00000000..e635927d
Binary files /dev/null and b/docs/images/pinlayout_example_topRight.png differ
diff --git a/docs/images/pinlayout_horizontallyBetween.png b/docs/images/pinlayout_horizontallyBetween.png
new file mode 100644
index 00000000..80eea2cd
Binary files /dev/null and b/docs/images/pinlayout_horizontallyBetween.png differ
diff --git a/docs/images/pinlayout_plus_layoutBox.png b/docs/images/pinlayout_plus_layoutBox.png
new file mode 100644
index 00000000..02684ef2
Binary files /dev/null and b/docs/images/pinlayout_plus_layoutBox.png differ
diff --git a/docs/images/pinlayout_right_to_left_example.png b/docs/images/pinlayout_right_to_left_example.png
new file mode 100644
index 00000000..d398a916
Binary files /dev/null and b/docs/images/pinlayout_right_to_left_example.png differ
diff --git a/docs/images/pinlayout_verticallyBetween.png b/docs/images/pinlayout_verticallyBetween.png
new file mode 100644
index 00000000..871d46fb
Binary files /dev/null and b/docs/images/pinlayout_verticallyBetween.png differ
diff --git a/docs/images/wrapContent_all.png b/docs/images/wrapContent_all.png
new file mode 100644
index 00000000..0f00ca0f
Binary files /dev/null and b/docs/images/wrapContent_all.png differ
diff --git a/docs/images/wrapContent_before.png b/docs/images/wrapContent_before.png
new file mode 100644
index 00000000..ad081829
Binary files /dev/null and b/docs/images/wrapContent_before.png differ
diff --git a/docs/images/wrapContent_example.png b/docs/images/wrapContent_example.png
new file mode 100644
index 00000000..c55fde13
Binary files /dev/null and b/docs/images/wrapContent_example.png differ
diff --git a/docs/images/wrapContent_horizontally.png b/docs/images/wrapContent_horizontally.png
new file mode 100644
index 00000000..d8079987
Binary files /dev/null and b/docs/images/wrapContent_horizontally.png differ
diff --git a/docs/images/wrapContent_padding.png b/docs/images/wrapContent_padding.png
new file mode 100644
index 00000000..b71b2303
Binary files /dev/null and b/docs/images/wrapContent_padding.png differ
diff --git a/docs/images/wrapContent_vertically.png b/docs/images/wrapContent_vertically.png
new file mode 100644
index 00000000..32b5af9b
Binary files /dev/null and b/docs/images/wrapContent_vertically.png differ
diff --git a/docs/objective_c.md b/docs/objective_c.md
index f1132fd0..6c17b258 100644
--- a/docs/objective_c.md
+++ b/docs/objective_c.md
@@ -9,21 +9,24 @@ PinLayout can also be used from Objective-C. The PinLayout interface is slightly
###### Example 1:
This example implement the PinLayout's Intro example using objective-c
-
+
```
- (void) layoutSubviews {
[super layoutSubviews];
-
- [[[[[[logo.pinObjc top] left] width:100] aspectRatio] marginWithTop:topLayoutGuide + 10 horizontal:10 bottom:10] layout];
- [[[[segmented.pinObjc rightOf:logo aligned:VerticalAlignTop] right] marginHorizontal:10] layout];
- [[[[[[textLabel.pinObjc belowOf:segmented aligned:HorizontalAlignLeft] widthOf:segmented] pinEdges] marginTop:10] fitSize] layout];
- [[[[[separatorView.pinObjc belowOfViews:@[logo, textLabel] aligned:HorizontalAlignLeft] rightTo:segmented.edge.right] height:1] marginTop:10] layout];
+
+ CGFloat margin = 10;
+ UIEdgeInsets safeArea = self.pinObjc.safeArea;
+
+ logo.pinObjc.topInsets(safeArea).leftInsets(safeArea).width(100).aspectRatio().margin(margin).layout();
+ segmented.pinObjc.rightOfAligned(logo, VerticalAlignTop).rightInsets(safeArea).marginHorizontal(margin).layout();
+ textLabel.pinObjc.belowOfAligned(segmented, HorizontalAlignLeft).widthOf(segmented).pinEdges().marginTop(margin).sizeToFitType(FitWidth).layout();
+ separatorView.pinObjc.belowOfViewsAligned(@[logo, textLabel], HorizontalAlignLeft).rightToEdge(segmented.edge.right).height(1).marginTop(margin).layout();
}
```
-:pushpin: This example is available in the Examples App. See example complete [source code](https://github.com/mirego/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/IntroObjectiveC/IntroObjectiveCView.m)
+:pushpin: This example is available in the Examples App. See example complete [source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/IntroObjectiveC/IntroObjectiveCView.m)
## Important notes about PinLayout's Objective-c interface
@@ -31,7 +34,7 @@ This example implement the PinLayout's Intro example using objective-c
The PinLayout's objective-c interface is available using the property `pinObjc` (instead of `pin` in Swift)
```
- [[view.pinObjc top] layout];
+ view.pinObjc.top().layout();
```
#### `layout()`
@@ -47,6 +50,6 @@ When using the Objective-c interface, the `layout` method must be called explici
view.pin.width(100)
// Objective-c
- [[view.pinObjc width:100] layout];
+ view.pinObjc.width(100).layout();
```
diff --git a/docs/pinlayout_example_adjust_to_container-landscape.png b/docs/pinlayout_example_adjust_to_container-landscape.png
index fb45561d..9e0693f4 100644
Binary files a/docs/pinlayout_example_adjust_to_container-landscape.png and b/docs/pinlayout_example_adjust_to_container-landscape.png differ
diff --git a/docs/pinlayout_example_wrapContent.png b/docs/pinlayout_example_wrapContent.png
new file mode 100644
index 00000000..372a06cb
Binary files /dev/null and b/docs/pinlayout_example_wrapContent.png differ
diff --git a/docs/pinlayout_exampleapp_automatic_sizing.png b/docs/pinlayout_exampleapp_automatic_sizing.png
new file mode 100644
index 00000000..77157fba
Binary files /dev/null and b/docs/pinlayout_exampleapp_automatic_sizing.png differ
diff --git a/docs/rtl_support.md b/docs/rtl_support.md
index 0db33396..8f86f9b0 100644
--- a/docs/rtl_support.md
+++ b/docs/rtl_support.md
@@ -37,4 +37,4 @@ override func layoutSubviews() {
}
```
-:pushpin: The complete RTL "Introduction example" [source code](https://github.com/mirego/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/IntroRTL/IntroRTLView.swift). This example is available in the [Examples App](#examples_app)
\ No newline at end of file
+:pushpin: The complete RTL "Introduction example" [source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/IntroRTL/IntroRTLView.swift). This example is available in the [Examples App](#examples_app)
\ No newline at end of file
diff --git a/docs/xcode_playground.md b/docs/xcode_playground.md
index 329f9680..37a92f4e 100644
--- a/docs/xcode_playground.md
+++ b/docs/xcode_playground.md
@@ -16,7 +16,7 @@ The method will execute PinLayout commands immediately. This method is **require
```swift
view.pin.top(20).bottom(20).width(100).layout()
- view2.pin.below(of: view).left().right().layout()
+ view2.pin.below(of: view).horizontally().layout()
```
**TIP**: If your codes needs to work in Xcode playgrounds, you may set to `true` the property `Pin.logMissingLayoutCalls`, this way any missing call to `layout()` will generate a warning in the Xcode console.
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
deleted file mode 100644
index 5622d104..00000000
--- a/fastlane/Fastfile
+++ /dev/null
@@ -1,126 +0,0 @@
-# Change the syntax highlighting to Ruby
-# All lines starting with a # are ignored when running `fastlane`
-
-# If you want to automatically update fastlane if a new version is available:
-# update_fastlane
-
-# This is the minimum version number required.
-# Update this, if you use features of a newer version
-fastlane_version "2.29.0"
-
-#default_platform :ios
-
-##### iOS platform
-##############################################
-platform :ios do
- before_all do
- end
-
- lane :install do
- bundle_install
- cocoapods(use_bundle_exec: true, try_repo_update_on_error: true)
- end
-
- lane :build do
- install
-
- swiftlint(
- mode: :lint,
- config_file: ".swiftlint.yml",
- executable: "Pods/SwiftLint/swiftlint"
- )
-
- xcodebuild(
- project: "PinLayout.xcodeproj",
- scheme: "PinLayout-iOS",
- destination: "name=iPhone 8 Plus,OS=11.2",
- #configuration: "Debug",
- build: true,
- clean: true
- )
-
- xcodebuild(
- project: "PinLayout.xcodeproj",
- scheme: "PinLayout-tvOS",
- destination: "name=Apple TV",
- build: true,
- clean: true
- )
-
- xcodebuild(
- workspace: "PinLayout.xcworkspace",
- scheme: "PinLayoutSample",
- build: true,
- clean: true,
- #destination: "name=iPhone 8 Plus,OS=11.2",
- destination: "generic/platform=iOS\" CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY=\""
- )
- end
-
- lane :tests do
- scan(
- scheme: "PinLayoutSample",
- workspace: "PinLayout.xcworkspace",
- devices: [
- "iPhone 7 (10.2)",
- "iPhone 7 (11.2)",
- "iPad Air (11.2)",
- "iPhone X (11.2)"
- ]
- )
- end
-
- lane :doc do
- jazzy
- end
-
- lane :travis do
- build
- tests
- pod_lib_lint(allow_warnings: true, verbose: false)
- end
-end
-
-
-##### MAC platform
-##############################################
-platform :mac do
- lane :install do
- bundle_install
- cocoapods(use_bundle_exec: true, try_repo_update_on_error: true)
- end
-
- lane :build do
- install
- xcodebuild(
- project: "PinLayout.xcodeproj",
- scheme: "PinLayout-macOS",
- #destination: "name=Apple TV",
- build: true
- #clean: true,
- #destination: "generic/platform=iOS\" CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY=\""
- )
-
- #xcodebuild(
- # workspace: "PinLayout.xcworkspace",
- # scheme: "PinLayoutSample",
- # build: true,
- # clean: true,
- # #destination: "name=iPhone 8 Plus,OS=11.2",
- # destination: "generic/platform=iOS\" CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY=\""
- #)
- end
-
- #lane :tests do
- # scan(
- # scheme: "PinLayout-macOS",
- # workspace: "PinLayout.xcworkspace",
- # destination: "platform=macOS,arch=x86_64"
- # )
- #end
-
- lane :travis do
- build
- # tests
- end
-end
diff --git a/index.md b/index.md
index 7095389e..eae3d345 100644
--- a/index.md
+++ b/index.md
@@ -1,17 +1,17 @@