diff --git a/README.md b/README.md index c604c20..855dc5a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A wonderful layout component called the [`UIStackView` was introduced with *iOS `UIStackView` requires *iOS 9*, but we're not ready to make our apps require *iOS 9+* just yet. In the meanwhile, we developers are eager to try this component in our apps right now! This is why I created this replica of the `UIStackView`, called the `TZStackView` (TZ = Tom van Zummeren, my initials). I created this component very carefully, tested every single corner case and matched the results against the *real* `UIStackView` with automated `XCTestCases`. ## Features -- ✅ Compatible with **iOS 7.x** and **iOS 8.x** +- ✅ Compatible with **iOS 8.x** or later - ✅ Supports the complete API of `UIStackView` including **all** *distribution* and *alignment* options - ✅ Supports animating the `hidden` property of the *arranged subviews* - ❌ Supports *Storyboard* diff --git a/TZStackView.xcodeproj/project.pbxproj b/TZStackView.xcodeproj/project.pbxproj index b9e35a1..5036245 100644 --- a/TZStackView.xcodeproj/project.pbxproj +++ b/TZStackView.xcodeproj/project.pbxproj @@ -16,10 +16,10 @@ 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 */; }; @@ -123,6 +123,7 @@ 5F50EB61965EE1FD3F76FB91 /* Products */, ); sourceTree = ""; + usesTabs = 0; }; 5F50E7526ADB7151E0540D2D /* TZStackViewTests */ = { isa = PBXGroup; @@ -404,7 +405,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -442,7 +443,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; @@ -517,7 +518,6 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = TZStackView/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = nl.tomvanzummeren.TZStackView; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -540,7 +540,6 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = TZStackView/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = nl.tomvanzummeren.TZStackView; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/TZStackView/TZStackView.swift b/TZStackView/TZStackView.swift index 2fd77a8..33a6c31 100755 --- a/TZStackView/TZStackView.swift +++ b/TZStackView/TZStackView.swift @@ -188,7 +188,6 @@ public class TZStackView: UIView { guideConstraint = constraint(item: arrangedSubview, attribute: .Width, toItem: nil, attribute: .NotAnAttribute, constant: 0, priority: 25) } subviewConstraints.append(guideConstraint) - arrangedSubview.addConstraint(guideConstraint) } if isHidden(arrangedSubview) { @@ -200,7 +199,6 @@ public class TZStackView: UIView { hiddenConstraint = constraint(item: arrangedSubview, attribute: .Height, toItem: nil, attribute: .NotAnAttribute, constant: 0) } subviewConstraints.append(hiddenConstraint) - arrangedSubview.addConstraint(hiddenConstraint) } } @@ -323,9 +321,10 @@ public class TZStackView: UIView { stackViewConstraints.append(constraint(item: self, attribute: .TopMargin, toItem: spacerViews[0])) } } - addConstraints(stackViewConstraints) } - + + NSLayoutConstraint.activateConstraints(subviewConstraints + stackViewConstraints) + super.updateConstraints() } @@ -476,12 +475,14 @@ 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) + case .LastBaseline: + constraints += equalAttributes(views: views, attribute: .LastBaseline) } case .Vertical: @@ -491,12 +492,14 @@ 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 += [] + case .LastBaseline: + constraints += [] } } return constraints diff --git a/TZStackView/TZStackViewAlignment.swift b/TZStackView/TZStackViewAlignment.swift index f99594f..5f1fc4b 100644 --- a/TZStackView/TZStackViewAlignment.swift +++ b/TZStackView/TZStackViewAlignment.swift @@ -9,11 +9,36 @@ import Foundation @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 - case Center + + /* 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 - case Top + public static var Top: TZStackViewAlignment { + get { + return .Leading + } + } + case FirstBaseline // Valid for horizontal axis only + + /* Center the items in a vertical stack horizontally + or the items in a horizontal stack vertically + */ + case Center + + /* 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 - case Bottom - case FirstBaseline + public static var Bottom: TZStackViewAlignment { get { + return .Trailing + } + } + case LastBaseline // Valid for horizontal axis only }