Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions TZStackView.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@
5F50E9F2F7E5B2DA68C946E0 /* ExplicitIntrinsicContentSizeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F50E5EB8202F5247F8517F3 /* ExplicitIntrinsicContentSizeView.swift */; };
5F50EAD959E8ACC5929DBD75 /* NSLayoutConstraintExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB41AF691B294B8E003DB902 /* NSLayoutConstraintExtension.swift */; };
5F50EF474D670FC33E8E80EA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5F50ED5A43FBFC32B9B9E1AA /* Images.xcassets */; };
7E214B741BF61501006448AC /* Storyboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7E214B731BF61501006448AC /* Storyboard.storyboard */; };
A45441C21B9B6D71002452BA /* TZStackView.h in Headers */ = {isa = PBXBuildFile; fileRef = A45441C11B9B6D71002452BA /* TZStackView.h */; settings = {ATTRIBUTES = (Public, ); }; };
A45441C61B9B6D71002452BA /* TZStackView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A45441BF1B9B6D71002452BA /* TZStackView.framework */; };
A45441C71B9B6D71002452BA /* TZStackView.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = A45441BF1B9B6D71002452BA /* TZStackView.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
A45441D01B9B6D9C002452BA /* TZSpacerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A45441CC1B9B6D9C002452BA /* TZSpacerView.swift */; settings = {ASSET_TAGS = (); }; };
A45441D11B9B6D9C002452BA /* TZStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A45441CD1B9B6D9C002452BA /* TZStackView.swift */; settings = {ASSET_TAGS = (); }; };
A45441D21B9B6D9C002452BA /* TZStackViewAlignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = A45441CE1B9B6D9C002452BA /* TZStackViewAlignment.swift */; settings = {ASSET_TAGS = (); }; };
A45441D31B9B6D9C002452BA /* TZStackViewDistribution.swift in Sources */ = {isa = PBXBuildFile; fileRef = A45441CF1B9B6D9C002452BA /* TZStackViewDistribution.swift */; settings = {ASSET_TAGS = (); }; };
A45441D01B9B6D9C002452BA /* TZSpacerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A45441CC1B9B6D9C002452BA /* TZSpacerView.swift */; };
A45441D11B9B6D9C002452BA /* TZStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A45441CD1B9B6D9C002452BA /* TZStackView.swift */; };
A45441D21B9B6D9C002452BA /* TZStackViewAlignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = A45441CE1B9B6D9C002452BA /* TZStackViewAlignment.swift */; };
A45441D31B9B6D9C002452BA /* TZStackViewDistribution.swift in Sources */ = {isa = PBXBuildFile; fileRef = A45441CF1B9B6D9C002452BA /* TZStackViewDistribution.swift */; };
DB41AF6A1B294B8E003DB902 /* NSLayoutConstraintExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB41AF691B294B8E003DB902 /* NSLayoutConstraintExtension.swift */; };
DB5B70851B2A1963006043BD /* TestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB5B70841B2A1963006043BD /* TestView.swift */; };
DB5B70871B2B8816006043BD /* TZStackViewTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB5B70861B2B8816006043BD /* TZStackViewTestCase.swift */; };
Expand Down Expand Up @@ -67,6 +68,7 @@
5F50EDEB0947F99E67140FC6 /* TZStackViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TZStackViewTests.swift; sourceTree = "<group>"; };
5F50EF54F01A3A6938C6CEA1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
5F50EFD0C46B7C7F989F10E1 /* TZStackViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TZStackViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
7E214B731BF61501006448AC /* Storyboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Storyboard.storyboard; sourceTree = "<group>"; };
A45441BF1B9B6D71002452BA /* TZStackView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TZStackView.framework; sourceTree = BUILT_PRODUCTS_DIR; };
A45441C11B9B6D71002452BA /* TZStackView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TZStackView.h; sourceTree = "<group>"; };
A45441C31B9B6D71002452BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -152,6 +154,7 @@
5F50ECF2FC09D64EB02F1309 /* ViewController.swift */,
5F50E5EB8202F5247F8517F3 /* ExplicitIntrinsicContentSizeView.swift */,
DB41AF691B294B8E003DB902 /* NSLayoutConstraintExtension.swift */,
7E214B731BF61501006448AC /* Storyboard.storyboard */,
DB614E5D1B292B630024E8AD /* LaunchScreen.xib */,
5F50ECF4A13687970498D9A7 /* Supporting Files */,
5F50ED5A43FBFC32B9B9E1AA /* Images.xcassets */,
Expand Down Expand Up @@ -298,6 +301,7 @@
files = (
DB614E5E1B292B630024E8AD /* LaunchScreen.xib in Resources */,
5F50EF474D670FC33E8E80EA /* Images.xcassets in Resources */,
7E214B741BF61501006448AC /* Storyboard.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
3 changes: 2 additions & 1 deletion TZStackView/TZStackView.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ FOUNDATION_EXPORT const unsigned char TZStackViewVersionString[];

// In this header, you should import all the public headers of your framework using statements like #import <TZStackView/PublicHeader.h>


#define TZStackViewAlignmentTop TZStackViewAlignmentLeading
#define TZStackViewAlignmentBottom TZStackViewAlignmentTrailing
81 changes: 71 additions & 10 deletions TZStackView/TZStackView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func ==(lhs: TZAnimationDidStopQueueEntry, rhs: TZAnimationDidStopQueueEntry) ->
return lhs.view === rhs.view
}

@IBDesignable
public class TZStackView: UIView {

public var distribution: TZStackViewDistribution = .Fill {
Expand All @@ -32,10 +33,37 @@ public class TZStackView: UIView {
}

public var alignment: TZStackViewAlignment = .Fill

@objc @IBInspectable private var axisValue: Int {
get {
return axis.rawValue
}
set {
axis = UILayoutConstraintAxis(rawValue: newValue) ?? .Horizontal
}
}

@objc @IBInspectable private var alignmentValue: Int {
get {
return alignment.rawValue
}
set {
alignment = TZStackViewAlignment(rawValue: newValue) ?? .Fill
}
}

@objc @IBInspectable private var distributionValue: Int {
get {
return distribution.rawValue
}
set {
distribution = TZStackViewDistribution(rawValue: newValue) ?? .Fill
}
}

public var spacing: CGFloat = 0
@objc @IBInspectable public var spacing: CGFloat = 0

public var layoutMarginsRelativeArrangement = false
@objc @IBInspectable public var layoutMarginsRelativeArrangement: Bool = false

public private(set) var arrangedSubviews: [UIView] = [] {
didSet {
Expand All @@ -59,6 +87,20 @@ public class TZStackView: UIView {

public init(arrangedSubviews: [UIView] = []) {
super.init(frame: CGRectZero)
commonInit(arrangedSubviews)
}

override public init(frame: CGRect) {
super.init(frame: frame)
commonInit([])
}

required public init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
commonInit([])
}

private func commonInit(arrangedSubviews: [UIView]) {
for arrangedSubview in arrangedSubviews {
arrangedSubview.translatesAutoresizingMaskIntoConstraints = false
addSubview(arrangedSubview)
Expand All @@ -72,7 +114,30 @@ public class TZStackView: UIView {
// This removes `hidden` value KVO observers using didSet()
{ self.arrangedSubviews = [] }()
}

override public func awakeFromNib() {
super.awakeFromNib()

// a hack, remove Interface Builder generated constraints that are not created by you
for aConstraint in constraints where NSStringFromClass(aConstraint.dynamicType) == "NSIBPrototypingLayoutConstraint" {
removeConstraint(aConstraint)
}

for aView in subviews {
addArrangedSubview(aView)
}
}

override public func prepareForInterfaceBuilder() {
if #available(iOS 8.0, *) {
super.prepareForInterfaceBuilder()

for aView in subviews {
addArrangedSubview(aView)
}
}
}

private func registerHiddenListeners(previousArrangedSubviews: [UIView]) {
for subview in previousArrangedSubviews {
self.removeHiddenListener(subview)
Expand Down Expand Up @@ -329,10 +394,6 @@ public class TZStackView: UIView {
super.updateConstraints()
}

required public init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
}

private func addSpacerView() -> TZSpacerView {
let spacerView = TZSpacerView()
spacerView.translatesAutoresizingMaskIntoConstraints = false
Expand Down Expand Up @@ -476,9 +537,9 @@ public class TZStackView: UIView {
constraints += equalAttributes(views: views, attribute: .Top)
case .Center:
constraints += equalAttributes(views: views, attribute: .CenterY)
case .Leading, .Top:
case .Leading:
constraints += equalAttributes(views: views, attribute: .Top)
case .Trailing, .Bottom:
case .Trailing:
constraints += equalAttributes(views: views, attribute: .Bottom)
case .FirstBaseline:
constraints += equalAttributes(views: views, attribute: .FirstBaseline)
Expand All @@ -491,9 +552,9 @@ public class TZStackView: UIView {
constraints += equalAttributes(views: views, attribute: .Trailing)
case .Center:
constraints += equalAttributes(views: views, attribute: .CenterX)
case .Leading, .Top:
case .Leading:
constraints += equalAttributes(views: views, attribute: .Leading)
case .Trailing, .Bottom:
case .Trailing:
constraints += equalAttributes(views: views, attribute: .Trailing)
case .FirstBaseline:
constraints += []
Expand Down
37 changes: 29 additions & 8 deletions TZStackView/TZStackViewAlignment.swift
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,33 @@

import Foundation

@objc public enum TZStackViewAlignment: Int {
case Fill
case Center
case Leading
case Top
case Trailing
case Bottom
case FirstBaseline
/* Alignment—the layout transverse to the stacking axis.
*/
@objc public enum TZStackViewAlignment : Int {

/* Align the leading and trailing edges of vertically stacked items
or the top and bottom edges of horizontally stacked items tightly to the container.
*/
case Fill = 0

/* Align the leading edges of vertically stacked items
or the top edges of horizontally stacked items tightly to the relevant edge
of the container
*/
case Leading = 1
public static let Top: TZStackViewAlignment = .Leading
case FirstBaseline = 2 // Valid for horizontal axis only

/* Center the items in a vertical stack horizontally
or the items in a horizontal stack vertically
*/
case Center = 3

/* Align the trailing edges of vertically stacked items
or the bottom edges of horizontally stacked items tightly to the relevant
edge of the container
*/
case Trailing = 4
public static let Bottom: TZStackViewAlignment = .Trailing
// case LastBaseline = 5 // Valid for horizontal axis only
}
47 changes: 41 additions & 6 deletions TZStackView/TZStackViewDistribution.swift
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,45 @@
//
import Foundation

@objc public enum TZStackViewDistribution: Int {
case Fill
case FillEqually
case FillProportionally
case EqualSpacing
case EqualCentering
/* Distribution—the layout along the stacking axis.

All UIStackViewDistribution enum values fit first and last arranged subviews tightly to the container,
and except for UIStackViewDistributionFillEqually, fit all items to intrinsicContentSize when possible.
*/
@objc public enum TZStackViewDistribution : Int {

/* When items do not fit (overflow) or fill (underflow) the space available
adjustments occur according to compressionResistance or hugging
priorities of items, or when that is ambiguous, according to arrangement
order.
*/
case Fill = 0

/* Items are all the same size.
When space allows, this will be the size of the item with the largest
intrinsicContentSize (along the axis of the stack).
Overflow or underflow adjustments are distributed equally among the items.
*/
case FillEqually = 1

/* Overflow or underflow adjustments are distributed among the items proportional
to their intrinsicContentSizes.
*/
case FillProportionally = 2

/* Additional underflow spacing is divided equally in the spaces between the items.
Overflow squeezing is controlled by compressionResistance priorities followed by
arrangement order.
*/
case EqualSpacing = 3

/* Equal center-to-center spacing of the items is maintained as much
as possible while still maintaining a minimum edge-to-edge spacing within the
allowed area.
Additional underflow spacing is divided equally in the spacing. Overflow
squeezing is distributed first according to compressionResistance priorities
of items, then according to subview order while maintaining the configured
(edge-to-edge) spacing as a minimum.
*/
case EqualCentering = 4
}
Loading