diff --git a/Example/StackLayoutExample/UI/Examples/LayoutModes/LayoutModesView.swift b/Example/StackLayoutExample/UI/Examples/LayoutModes/LayoutModesView.swift index 4a1296e..528c45d 100644 --- a/Example/StackLayoutExample/UI/Examples/LayoutModes/LayoutModesView.swift +++ b/Example/StackLayoutExample/UI/Examples/LayoutModes/LayoutModesView.swift @@ -33,6 +33,7 @@ class LayoutModesView: BaseView { super.init() stackView.direction(.column).define { (stack) in + stack.spacing(4) // only for .distribution stack.addItem(BasicView(text: "View 1")) stack.addItem(BasicView(text: "View 2")) stack.addItem(BasicView(text: "View 3")) @@ -114,7 +115,8 @@ class LayoutModesView: BaseView { case .end: stackView.justifyContent(.spaceBetween) case .spaceBetween: stackView.justifyContent(.spaceAround) case .spaceAround: stackView.justifyContent(.spaceEvenly) - case .spaceEvenly: stackView.justifyContent(.start) + case .spaceEvenly: stackView.justifyContent(.distribution) + case .distribution: stackView.justifyContent(.start) } applyChange() @@ -152,6 +154,7 @@ class LayoutModesView: BaseView { case .spaceBetween: justifyLabel.text = ".spaceBetween" case .spaceAround: justifyLabel.text = ".spaceAround" case .spaceEvenly: justifyLabel.text = ".spaceEvenly" + case .distribution: justifyLabel.text = ".distribution" } switch stackView.getAlignItems() { @@ -161,6 +164,7 @@ class LayoutModesView: BaseView { case .end: alignItemsLabel.text = ".end" } + justifyLabel.sizeToFit() buttonsStackView.markDirty() } } diff --git a/Example/StackLayoutExample/UI/Examples/UnitTests/UnitTestsView.swift b/Example/StackLayoutExample/UI/Examples/UnitTests/UnitTestsView.swift index 9cd3492..90ec6db 100644 --- a/Example/StackLayoutExample/UI/Examples/UnitTests/UnitTestsView.swift +++ b/Example/StackLayoutExample/UI/Examples/UnitTests/UnitTestsView.swift @@ -300,6 +300,7 @@ class UnitTestsView: BaseView { case .spaceBetween: stackView.justifyContent(.spaceAround) case .spaceAround: stackView.justifyContent(.spaceEvenly) case .spaceEvenly: stackView.justifyContent(.start) + case .distribution: stackView.justifyContent(.distribution) } setNeedsLayout() diff --git a/Sources/Impl/Container.swift b/Sources/Impl/Container.swift index 0e1689e..95efefb 100644 --- a/Sources/Impl/Container.swift +++ b/Sources/Impl/Container.swift @@ -21,7 +21,7 @@ import UIKit class Container { - fileprivate let stackView: StackView + unowned fileprivate let stackView: StackView var width: CGFloat? var height: CGFloat? var innerWidth: CGFloat? @@ -75,6 +75,8 @@ class Container { var mainAxisTotalItemsLength: CGFloat = 0 + var mainAxisTotalItemsMargin: CGFloat = 0 + init(_ stackView: StackView) { self.stackView = stackView } @@ -128,6 +130,7 @@ class Container { items.forEach({ (item) in mainAxisTotalItemsLength += item.mainAxisStartMargin + mainAxisTotalItemsMargin += item.mainAxisStartMargin if direction == .column { mainAxisTotalItemsLength += (item.height != nil ? item.height! : 0) @@ -136,6 +139,7 @@ class Container { } mainAxisTotalItemsLength += item.mainAxisEndMargin + mainAxisTotalItemsMargin += item.mainAxisEndMargin }) } diff --git a/Sources/Impl/ItemInfo.swift b/Sources/Impl/ItemInfo.swift index 13e598c..2cb9a8d 100644 --- a/Sources/Impl/ItemInfo.swift +++ b/Sources/Impl/ItemInfo.swift @@ -20,9 +20,9 @@ import UIKit class ItemInfo { - var view: UIView - var stackItem: StackItemImpl - var container: Container + unowned let view: UIView + unowned let stackItem: StackItemImpl + unowned let container: Container private var _width: CGFloat? var width: CGFloat? { diff --git a/Sources/Impl/StackItemImpl.swift b/Sources/Impl/StackItemImpl.swift index d064ead..b8581c3 100644 --- a/Sources/Impl/StackItemImpl.swift +++ b/Sources/Impl/StackItemImpl.swift @@ -30,7 +30,7 @@ enum MeasureType { class StackItemImpl: NSObject, StackItem { - internal let view: UIView + unowned internal let view: UIView internal var width: Value? internal var minWidth: Value? diff --git a/Sources/Impl/StackView+Layout.swift b/Sources/Impl/StackView+Layout.swift index b395878..4945a56 100644 --- a/Sources/Impl/StackView+Layout.swift +++ b/Sources/Impl/StackView+Layout.swift @@ -64,6 +64,20 @@ extension StackView { private func adjustItemsSizeToContainer(container: Container) { guard let mainAxisInnerLength = container.mainAxisInnerLength else { return } + + if self.justifyContent == .distribution { + let count = CGFloat(container.items.count) + let gap = max(count - 1, 0) * (_spacing?.value ?? 0) + container.mainAxisTotalItemsMargin + let len = (mainAxisInnerLength - gap) / count + for item in container.items { + if self.direction == .column { + item.height = len + } else { + item.width = len + } + } + return + } var previousLength: CGFloat? var lengthDiff = mainAxisInnerLength - container.mainAxisTotalItemsLength @@ -164,6 +178,8 @@ extension StackView { case .spaceEvenly: betweenSpacing = (containerMainAxisInnner - mainAxisTotalItemsLength) / CGFloat(container.items.count + 1) startEndSpacing = betweenSpacing + case .distribution: + betweenSpacing = _spacing?.value ?? 0 } } diff --git a/Sources/StackView.swift b/Sources/StackView.swift index fd156b8..a17e060 100644 --- a/Sources/StackView.swift +++ b/Sources/StackView.swift @@ -33,6 +33,8 @@ public class StackView: UIView { internal var _paddingBottom: Value? internal var _paddingRight: Value? internal var _paddingEnd: Value? + + internal var _spacing: Value? public override init(frame: CGRect) { super.init(frame: frame) @@ -322,6 +324,25 @@ public class StackView: UIView { return self } + // + // MARK: Spacing + // + + /** + The `spacing` property only for justify .distribution in the StackView. + + - Parameter value: Default value is 0 + */ + @discardableResult + public func spacing(_ spacing: CGFloat) -> StackView { + _spacing = Value(spacing) + return self + } + + public func getSpacing() -> CGFloat { + return _spacing?.value ?? 0 + } + // // Layout view // diff --git a/Sources/Types.swift b/Sources/Types.swift index 19a7a92..51b07e5 100644 --- a/Sources/Types.swift +++ b/Sources/Types.swift @@ -47,6 +47,8 @@ public enum SJustifyContent { case spaceAround /// Items are positioned with space before, between, and after items case spaceEvenly + /// Items are adjusted to same length in main axis, with space and margin between them + case distribution } /**