diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..16e143c Binary files /dev/null and b/.DS_Store differ diff --git a/README.md b/README.md index 47045d2..30d1a75 100644 --- a/README.md +++ b/README.md @@ -1367,17 +1367,17 @@ The property expose the `UIKit` value [`UIView.keyboardLayoutGuide`](https://dev ## WrapContent -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. +The following methods are useful to adjust view's width and/or height to wrap all its subviews that are included in the layout. 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's position to create a tight wrap. It is also possible to specify an optional padding around all subviews. +Adjust the view's width and height to wrap all its subviews that are included in the layout. The method also adjusts subviews's 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. Accept a WrapType parameter to define the wrapping type. It is also possible to specify an optional padding around all subviews. +Adjust the view's width AND/OR height to wrap all its subviews that are included in the layout. Accept a WrapType parameter to define the wrapping type. It is also possible to specify an optional padding around all subviews. **Types:** diff --git a/Sources/Extensions/UIView+PinLayout.swift b/Sources/Extensions/UIView+PinLayout.swift index 1a9c144..d6a7e10 100644 --- a/Sources/Extensions/UIView+PinLayout.swift +++ b/Sources/Extensions/UIView+PinLayout.swift @@ -133,7 +133,7 @@ extension UIView: AutoSizeCalculable { layoutClosure() - let boundingRect = subviews.compactMap({ $0.autoSizingRectWithMargins }).reduce(CGRect.zero) { (result: CGRect, autoSizingRect: CGRect) -> CGRect in + let boundingRect = subviewsIncludedInSizeCalculation.compactMap({ $0.autoSizingRectWithMargins }).reduce(CGRect.zero) { (result: CGRect, autoSizingRect: CGRect) -> CGRect in return result.union(autoSizingRect) } diff --git a/Sources/Layoutable.swift b/Sources/Layoutable.swift index fa4e996..cb70407 100644 --- a/Sources/Layoutable.swift +++ b/Sources/Layoutable.swift @@ -36,3 +36,23 @@ public protocol Layoutable: AnyObject, Equatable, CustomDebugStringConvertible { func isLTR() -> Bool } + +private struct pinlayoutAssociatedKeys { + static var pinlayoutIsIncludedInSizeCalculation = UnsafeMutablePointer.allocate(capacity: 1) +} + +extension Layoutable { + + var isIncludedInSizeCalculation: Bool { + get { + return objc_getAssociatedObject(self, &pinlayoutAssociatedKeys.pinlayoutIsIncludedInSizeCalculation) as? Bool ?? true + } + set { + objc_setAssociatedObject(self, &pinlayoutAssociatedKeys.pinlayoutIsIncludedInSizeCalculation, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } + + var subviewsIncludedInSizeCalculation: [PinView] { + return subviews.filter(\.isIncludedInSizeCalculation) + } +} diff --git a/Sources/PinLayout+WrapContent.swift b/Sources/PinLayout+WrapContent.swift index e58731c..be59757 100644 --- a/Sources/PinLayout+WrapContent.swift +++ b/Sources/PinLayout+WrapContent.swift @@ -25,7 +25,7 @@ import AppKit extension PinLayout { /** - Adjust the view's width & height to wrap all its subviews. The method also adjust subviews position to create a tight wrap. + Adjust the view's width & height to wrap all its subviews that are included in the size calculation. The method also adjust subviews position to create a tight wrap. */ @discardableResult public func wrapContent() -> PinLayout { @@ -33,7 +33,7 @@ extension PinLayout { } /** - Adjust the view's width & height to wrap all its subviews. The method also adds a padding around all subviews. + Adjust the view's width & height to wrap all its subviews that are included in the size calculation. The method also adds a padding around all subviews. - Parameters: - padding: Specify a padding value. @@ -45,7 +45,7 @@ extension PinLayout { /** The method... - - Adjust the view's width and height to wrap all its subviews. + - Adjust the view's width and height to wrap all its subviews that are included in the size calculation. - Adjust subviews's position to create a tight wrap. - Apply padding around all subviews. @@ -59,7 +59,7 @@ extension PinLayout { /** The method... - - Adjust the view's width and height to wrap all its subviews. + - Adjust the view's width and height to wrap all its subviews that are included in the size calculation. - Adjust subviews's position to create a tight wrap. - Parameters: @@ -72,7 +72,7 @@ extension PinLayout { /** The method... - - Adjust the view's width and height to wrap all its subviews. + - Adjust the view's width and height to wrap all its subviews that are included in the size calculation. - Adjust subviews's position to create a tight wrap. - Apply padding around all subviews. @@ -87,7 +87,7 @@ extension PinLayout { /** The method... - - Adjust the view's width and height to wrap all its subviews. + - Adjust the view's width and height to wrap all its subviews that are included in the size calculation. - Adjust subviews's position to create a tight wrap. - Apply padding around all subviews. @@ -101,11 +101,11 @@ extension PinLayout { } private func wrapContent(_ type: WrapType, padding: PEdgeInsets, _ context: Context) -> PinLayout { - let subviews = view.subviews - guard !subviews.isEmpty else { return self } + let includedSubviews = view.subviewsIncludedInSizeCalculation + guard !includedSubviews.isEmpty else { return self } - let firstViewRect = subviews[0].getRect(keepTransform: keepTransform) - let boundingRect = subviews.reduce(firstViewRect, { (result, view) in + let firstViewRect = includedSubviews[0].getRect(keepTransform: keepTransform) + let boundingRect = includedSubviews.reduce(firstViewRect, { (result, view) in result.union(view.getRect(keepTransform: keepTransform)) }) @@ -131,7 +131,7 @@ extension PinLayout { } if offsetDx != 0 || offsetDy != 0 { - subviews.forEach { (view) in + includedSubviews.forEach { (view) in let viewRect = view.getRect(keepTransform: keepTransform) let newRect = viewRect.offsetBy(dx: offsetDx, dy: offsetDy) view.setRect(newRect, keepTransform: keepTransform) diff --git a/Sources/PinLayout.swift b/Sources/PinLayout.swift index 33d79e3..41b78ef 100644 --- a/Sources/PinLayout.swift +++ b/Sources/PinLayout.swift @@ -84,6 +84,16 @@ public class PinLayout { apply() } + /// A Boolean value that determines whether the view is included in the PinLayout's size calculation. + /// + /// An excluded view does not take up space in the layout + /// when using `wrapContent(_:padding:_:)` or `autoSizeThatFits(_:layoutClosure:)`. + /// The default value is `true`. + public var isIncludedInSizeCalculation: Bool { + get { return view.isIncludedInSizeCalculation } + set { view.isIncludedInSizeCalculation = newValue } + } + #if os(iOS) || os(tvOS) public var safeArea: PEdgeInsets { if let view = view as? UIView { diff --git a/Sources/Types.swift b/Sources/Types.swift index 90ab6bb..1635999 100644 --- a/Sources/Types.swift +++ b/Sources/Types.swift @@ -186,11 +186,11 @@ public enum FitType { } @objc public enum WrapType: Int { - /// Adjust the view's width AND height to wrap all its subviews. + /// Adjust the view's width AND height to wrap all its subviews that are included in the size calculation. case all - /// Adjust only the view's width to wrap all its subviews. The view's height won't be modified. + /// Adjust only the view's width to wrap all its subviews that are included in the size calculation. The view's height won't be modified. case horizontally - /// Adjust only the view's height to wrap all its subviews. The view's width won't be modified. + /// Adjust only the view's height to wrap all its subviews that are included in the size calculation. The view's width won't be modified. case vertically }