Skip to content

Commit b88e7a8

Browse files
authored
Merge pull request #58 from seedco/dm/readable-width
Added ContentWidth
2 parents d35f776 + 4fc2be9 commit b88e7a8

File tree

9 files changed

+147
-15
lines changed

9 files changed

+147
-15
lines changed

Example/Info.plist

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
33
<plist version="1.0">
44
<dict>
5-
<key>NSPhotoLibraryUsageDescription</key>
6-
<string>Photo Library Access</string>
75
<key>CFBundleDevelopmentRegion</key>
86
<string>en</string>
97
<key>CFBundleExecutable</key>
@@ -24,6 +22,8 @@
2422
<string>1</string>
2523
<key>LSRequiresIPhoneOS</key>
2624
<true/>
25+
<key>NSPhotoLibraryUsageDescription</key>
26+
<string>Photo Library Access</string>
2727
<key>UILaunchStoryboardName</key>
2828
<string>LaunchScreen</string>
2929
<key>UIRequiredDeviceCapabilities</key>
@@ -35,6 +35,7 @@
3535
<string>UIInterfaceOrientationPortrait</string>
3636
<string>UIInterfaceOrientationLandscapeLeft</string>
3737
<string>UIInterfaceOrientationLandscapeRight</string>
38+
<string>UIInterfaceOrientationPortraitUpsideDown</string>
3839
</array>
3940
</dict>
4041
</plist>

SeedStackViewController.podspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Pod::Spec.new do |s|
22
s.name = "SeedStackViewController"
33
s.module_name = "StackViewController"
4-
s.version = "0.5.3"
4+
s.version = "0.6.0"
55
s.summary = "Simplifies the process of building forms and other static content using UIStackView."
66
s.description = "StackViewController is a Swift framework that simplifies the process of building forms and other static content using UIStackView."
77
s.homepage = "https://github.com/seedco/StackViewController"
@@ -11,7 +11,7 @@ Pod::Spec.new do |s|
1111
git: "https://github.com/seedco/StackViewController.git",
1212
tag: s.version.to_s
1313
}
14-
s.ios.deployment_target = "9.0"
14+
s.ios.deployment_target = "12.0"
1515
s.source_files = "StackViewController/*.{h,swift}"
1616
s.frameworks = "UIKit"
1717
s.swift_versions = "5.0"

StackViewController.xcodeproj/project.pbxproj

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
72DE37271CCDC769009CAE32 /* ImageAttachmentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72DE37261CCDC769009CAE32 /* ImageAttachmentViewController.swift */; };
3030
72DE37291CCDCCB6009CAE32 /* UIStackViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72DE37281CCDCCB6009CAE32 /* UIStackViewExtensions.swift */; };
3131
72DE372B1CCDD998009CAE32 /* ImageThumbnailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72DE372A1CCDD998009CAE32 /* ImageThumbnailView.swift */; };
32+
756AE907270B9DA000644AC5 /* ContentWidth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 756AE906270B9DA000644AC5 /* ContentWidth.swift */; };
3233
/* End PBXBuildFile section */
3334

3435
/* Begin PBXContainerItemProxy section */
@@ -88,6 +89,7 @@
8889
72DE37261CCDC769009CAE32 /* ImageAttachmentViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageAttachmentViewController.swift; sourceTree = "<group>"; };
8990
72DE37281CCDCCB6009CAE32 /* UIStackViewExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIStackViewExtensions.swift; sourceTree = "<group>"; };
9091
72DE372A1CCDD998009CAE32 /* ImageThumbnailView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageThumbnailView.swift; sourceTree = "<group>"; };
92+
756AE906270B9DA000644AC5 /* ContentWidth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentWidth.swift; sourceTree = "<group>"; };
9193
/* End PBXFileReference section */
9294

9395
/* Begin PBXFrameworksBuildPhase section */
@@ -144,6 +146,7 @@
144146
children = (
145147
72D193E61CC3576A00645F83 /* StackViewController.h */,
146148
72D193FB1CC3577B00645F83 /* AutoScrollView.swift */,
149+
756AE906270B9DA000644AC5 /* ContentWidth.swift */,
147150
72D193FD1CC3577B00645F83 /* SeparatorView.swift */,
148151
72D193FE1CC3577B00645F83 /* StackViewContainer.swift */,
149152
72D193FF1CC3577B00645F83 /* StackViewController.swift */,
@@ -258,7 +261,7 @@
258261
isa = PBXProject;
259262
attributes = {
260263
LastSwiftUpdateCheck = 0730;
261-
LastUpgradeCheck = 1110;
264+
LastUpgradeCheck = 1300;
262265
ORGANIZATIONNAME = "Seed Platform, Inc";
263266
TargetAttributes = {
264267
72D193E31CC3576A00645F83 = {
@@ -326,6 +329,7 @@
326329
isa = PBXSourcesBuildPhase;
327330
buildActionMask = 2147483647;
328331
files = (
332+
756AE907270B9DA000644AC5 /* ContentWidth.swift in Sources */,
329333
72DE37211CCDABA8009CAE32 /* UIViewExtensions.swift in Sources */,
330334
72D194031CC3577B00645F83 /* SeparatorView.swift in Sources */,
331335
72DE37291CCDCCB6009CAE32 /* UIStackViewExtensions.swift in Sources */,
@@ -410,6 +414,7 @@
410414
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
411415
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
412416
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
417+
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
413418
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
414419
CLANG_WARN_STRICT_PROTOTYPES = YES;
415420
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -434,7 +439,7 @@
434439
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
435440
GCC_WARN_UNUSED_FUNCTION = YES;
436441
GCC_WARN_UNUSED_VARIABLE = YES;
437-
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
442+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
438443
MTL_ENABLE_DEBUG_INFO = YES;
439444
ONLY_ACTIVE_ARCH = YES;
440445
SDKROOT = iphoneos;
@@ -466,6 +471,7 @@
466471
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
467472
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
468473
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
474+
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
469475
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
470476
CLANG_WARN_STRICT_PROTOTYPES = YES;
471477
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -484,7 +490,7 @@
484490
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
485491
GCC_WARN_UNUSED_FUNCTION = YES;
486492
GCC_WARN_UNUSED_VARIABLE = YES;
487-
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
493+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
488494
MTL_ENABLE_DEBUG_INFO = NO;
489495
SDKROOT = iphoneos;
490496
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
@@ -504,7 +510,7 @@
504510
DYLIB_INSTALL_NAME_BASE = "@rpath";
505511
INFOPLIST_FILE = StackViewController/Info.plist;
506512
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
507-
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
513+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
508514
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
509515
PRODUCT_BUNDLE_IDENTIFIER = co.seed.StackViewController;
510516
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -529,7 +535,7 @@
529535
DYLIB_INSTALL_NAME_BASE = "@rpath";
530536
INFOPLIST_FILE = StackViewController/Info.plist;
531537
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
532-
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
538+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
533539
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
534540
PRODUCT_BUNDLE_IDENTIFIER = co.seed.StackViewController;
535541
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -573,6 +579,7 @@
573579
PRODUCT_BUNDLE_IDENTIFIER = co.seed.Example;
574580
PRODUCT_NAME = "$(TARGET_NAME)";
575581
SWIFT_VERSION = 5.0;
582+
TARGETED_DEVICE_FAMILY = "1,2";
576583
};
577584
name = Debug;
578585
};
@@ -586,6 +593,7 @@
586593
PRODUCT_BUNDLE_IDENTIFIER = co.seed.Example;
587594
PRODUCT_NAME = "$(TARGET_NAME)";
588595
SWIFT_VERSION = 5.0;
596+
TARGETED_DEVICE_FAMILY = "1,2";
589597
};
590598
name = Release;
591599
};

StackViewController.xcodeproj/xcshareddata/xcschemes/Example.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "1110"
3+
LastUpgradeVersion = "1300"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"

StackViewController.xcodeproj/xcshareddata/xcschemes/StackViewController.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "1110"
3+
LastUpgradeVersion = "1300"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"

StackViewController/AutoScrollView.swift

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,34 +28,121 @@ open class AutoScrollView: UIScrollView {
2828
}
2929
didSet {
3030
if let contentView = contentView {
31+
contentView.translatesAutoresizingMaskIntoConstraints = false
3132
addSubview(contentView)
3233
updateContentViewConstraints()
3334
}
3435
}
3536
}
3637
fileprivate var contentViewConstraints: [NSLayoutConstraint]?
3738

39+
/// This layout guide follows the `contentView` and honors the `horizontallyCompactContentWidth`
40+
/// and `horizontallyRegularContentWidth` values.
41+
public var contentViewLayoutGuide = UILayoutGuide()
42+
private var contentViewLayoutGuideConstraints: [NSLayoutConstraint] = []
43+
44+
/// This setting determines how the content should be laid out in a horizontally compact environment.
45+
public var horizontallyCompactContentWidth: ContentWidth = .matchScrollViewWidth {
46+
didSet {
47+
guard horizontallyCompactContentWidth != oldValue else { return }
48+
49+
switch traitCollection.horizontalSizeClass {
50+
case .compact: updateContentViewConstraints()
51+
case .regular, .unspecified: break // no-op
52+
@unknown default: break
53+
}
54+
}
55+
}
56+
57+
/// This setting determines how the content should be laid out in a horizontally regular environment.
58+
public var horizontallyRegularContentWidth: ContentWidth = .matchScrollViewWidth {
59+
didSet {
60+
guard horizontallyRegularContentWidth != oldValue else { return }
61+
62+
switch traitCollection.horizontalSizeClass {
63+
case .regular: updateContentViewConstraints()
64+
case .compact, .unspecified: break // no-op
65+
@unknown default: break
66+
}
67+
}
68+
}
69+
3870
override open var contentInset: UIEdgeInsets {
3971
didSet {
4072
updateContentViewConstraints()
4173
}
4274
}
4375

4476
fileprivate func updateContentViewConstraints() {
77+
let contentViewFollowsReadableWidth: Bool
78+
switch traitCollection.horizontalSizeClass {
79+
case .compact:
80+
switch horizontallyCompactContentWidth {
81+
case .matchScrollViewWidth:
82+
contentViewFollowsReadableWidth = false
83+
case .matchReadableContentGuideWidth:
84+
contentViewFollowsReadableWidth = true
85+
}
86+
87+
case .regular:
88+
switch horizontallyRegularContentWidth {
89+
case .matchScrollViewWidth:
90+
contentViewFollowsReadableWidth = false
91+
case .matchReadableContentGuideWidth:
92+
contentViewFollowsReadableWidth = true
93+
}
94+
95+
case .unspecified:
96+
return // abort early
97+
98+
@unknown default:
99+
contentViewFollowsReadableWidth = false
100+
}
101+
45102
if let constraints = contentViewConstraints {
46103
NSLayoutConstraint.deactivate(constraints)
47104
}
48-
if let contentView = contentView {
49-
contentViewConstraints = contentView.activateSuperviewHuggingConstraints(insets: contentInset)
105+
NSLayoutConstraint.deactivate(contentViewLayoutGuideConstraints)
106+
107+
let newLayoutGuide: UILayoutGuide
108+
if contentViewFollowsReadableWidth, let contentView = contentView {
109+
let newConstraints = [
110+
contentView.leadingAnchor.constraint(
111+
equalTo: readableContentGuide.leadingAnchor,
112+
constant: contentInset.left
113+
),
114+
contentView.trailingAnchor.constraint(
115+
equalTo: readableContentGuide.trailingAnchor,
116+
constant: -contentInset.right
117+
),
118+
contentView.topAnchor.constraint(equalTo: topAnchor, constant: contentInset.top),
119+
contentView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -contentInset.bottom),
120+
]
121+
NSLayoutConstraint.activate(newConstraints)
122+
contentViewConstraints = newConstraints
123+
124+
newLayoutGuide = readableContentGuide
50125
} else {
51-
contentViewConstraints = nil
126+
contentViewConstraints = contentView?.activateSuperviewHuggingConstraints(insets: contentInset)
127+
128+
newLayoutGuide = frameLayoutGuide
52129
}
130+
131+
contentViewLayoutGuideConstraints = [
132+
contentViewLayoutGuide.leadingAnchor.constraint(equalTo: newLayoutGuide.leadingAnchor),
133+
contentViewLayoutGuide.topAnchor.constraint(equalTo: newLayoutGuide.topAnchor),
134+
contentViewLayoutGuide.trailingAnchor.constraint(equalTo: newLayoutGuide.trailingAnchor),
135+
contentViewLayoutGuide.bottomAnchor.constraint(equalTo: newLayoutGuide.bottomAnchor),
136+
]
137+
NSLayoutConstraint.activate(contentViewLayoutGuideConstraints)
53138
}
54139

55140
fileprivate func commonInit() {
56141
let nc = NotificationCenter.default
57142
nc.addObserver(self, selector: #selector(AutoScrollView.keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
58143
nc.addObserver(self, selector: #selector(AutoScrollView.keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
144+
145+
addLayoutGuide(contentViewLayoutGuide)
59146
}
60147

61148
public override init(frame: CGRect) {
@@ -77,6 +164,14 @@ open class AutoScrollView: UIScrollView {
77164
return true
78165
}
79166

167+
open override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
168+
guard traitCollection.horizontalSizeClass != previousTraitCollection?.horizontalSizeClass else {
169+
return
170+
}
171+
172+
updateContentViewConstraints()
173+
}
174+
80175
// MARK: Notifications
81176

82177
// Implementation based on code from Apple documentation
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// ContentWidth.swift
3+
// StackViewController
4+
//
5+
// Created by Devin McKaskle on 10/4/21.
6+
// Copyright © 2021 Seed Platform, Inc. All rights reserved.
7+
//
8+
9+
@objc public enum ContentWidth: Int {
10+
case matchScrollViewWidth
11+
case matchReadableContentGuideWidth
12+
13+
public mutating func toggle() {
14+
self = ContentWidth(rawValue: rawValue + 1) ?? .matchScrollViewWidth
15+
}
16+
}

StackViewController/StackViewContainer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ open class StackViewContainer: UIView, UIScrollViewDelegate {
150150
}
151151
}()
152152
stackViewSizeConstraint =
153-
NSLayoutConstraint(item: stackView, attribute: attribute, relatedBy: .equal, toItem: scrollView, attribute: attribute, multiplier: 1.0, constant: 0.0)
153+
NSLayoutConstraint(item: stackView, attribute: attribute, relatedBy: .equal, toItem: scrollView.contentViewLayoutGuide, attribute: attribute, multiplier: 1.0, constant: 0.0)
154154
stackViewSizeConstraint?.isActive = true
155155
}
156156

StackViewController/StackViewController.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,18 @@ open class StackViewController: UIViewController {
7070
open var scrollView: UIScrollView {
7171
return stackViewContainer.scrollView
7272
}
73+
74+
/// This setting determines how the content should be laid out in a horizontally compact environment.
75+
public var horizontallyCompactContentWidth: ContentWidth {
76+
get { stackViewContainer.scrollView.horizontallyCompactContentWidth }
77+
set { stackViewContainer.scrollView.horizontallyCompactContentWidth = newValue }
78+
}
79+
80+
/// This setting determines how the content should be laid out in a horizontally regular environment.
81+
public var horizontallyRegularContentWidth: ContentWidth {
82+
get { stackViewContainer.scrollView.horizontallyRegularContentWidth }
83+
set { stackViewContainer.scrollView.horizontallyRegularContentWidth = newValue }
84+
}
7385

7486
private lazy var stackViewContainer = StackViewContainer()
7587

0 commit comments

Comments
 (0)