Skip to content

Commit e48b54f

Browse files
authored
Merge pull request #28 from iWECon/dev
dev
2 parents ba6ffa6 + 054a3cf commit e48b54f

File tree

9 files changed

+95
-111
lines changed

9 files changed

+95
-111
lines changed

Demo/Demo.xcodeproj/project.pbxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,13 @@
7474
08E16CD8289ABA1C0019D7CB /* AppDelegate.swift */,
7575
08E16CDA289ABA1C0019D7CB /* SceneDelegate.swift */,
7676
080677C528BE7D8B00000E16 /* ViewController.swift */,
77+
0815C092292A2B37001655C6 /* Preview1ViewController.swift */,
7778
08E16CDC289ABA1C0019D7CB /* HVStackDemoViewController.swift */,
7879
080677C728BE7DA400000E16 /* WrapStackDemoViewController.swift */,
7980
08E16CDE289ABA1C0019D7CB /* Main.storyboard */,
8081
08E16CE1289ABA1D0019D7CB /* Assets.xcassets */,
8182
08E16CE3289ABA1D0019D7CB /* LaunchScreen.storyboard */,
8283
08E16CE6289ABA1D0019D7CB /* Info.plist */,
83-
0815C092292A2B37001655C6 /* Preview1ViewController.swift */,
8484
);
8585
path = Demo;
8686
sourceTree = "<group>";

Demo/Demo/Base.lproj/Main.storyboard

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
</viewController>
7575
<placeholder placeholderIdentifier="IBFirstResponder" id="NVa-Eg-Ijb" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
7676
</objects>
77-
<point key="canvasLocation" x="3648" y="-550"/>
77+
<point key="canvasLocation" x="1849" y="-581"/>
7878
</scene>
7979
<!--H/VStackView-->
8080
<scene sceneID="Lai-fH-3ho">

Demo/Demo/HVStackDemoViewController.swift

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -153,35 +153,31 @@ class HVStackDemoViewController: UIViewController {
153153

154154
let descriptionContent = VStackView {
155155
Spacer(length: 12)
156-
HStackView {
157-
Spacer(length: 12)
156+
VStackView(alignment: .left, distribution: .spacing(24)) {
157+
UILabel().stack.then {
158+
$0.font = .systemFont(ofSize: 20, weight: .semibold)
159+
$0.text = "⚠️ Important"
160+
}
161+
UILabel().stack.maxWidth(UIScreen.main.bounds.width - 48).then {
162+
$0.textColor = .systemPink
163+
$0.font = .systemFont(ofSize: 14, weight: .medium)
164+
$0.numberOfLines = 0
165+
$0.text = "`Spacer` will ignore the given spacing in H/VStack\nSpacer 会忽略在 H/VStack 中给定的 spacing, 也就是说可以使用 Spacer 自由调整 spacing"
166+
}
158167

159-
VStackView(alignment: .left, distribution: .spacing(24)) {
160-
UILabel().stack.then {
161-
$0.font = .systemFont(ofSize: 20, weight: .semibold)
162-
$0.text = "⚠️ Important"
163-
}
164-
UILabel().stack.maxWidth(UIScreen.main.bounds.width - 48).then {
165-
$0.textColor = .systemPink
166-
$0.font = .systemFont(ofSize: 14, weight: .medium)
167-
$0.numberOfLines = 0
168-
$0.text = "`Spacer` will ignore the given spacing in H/VStack\nSpacer 会忽略在 H/VStack 中给定的 spacing, 也就是说可以使用 Spacer 自由调整 spacing"
169-
}
170-
171-
UILabel().stack.then {
172-
$0.textColor = .systemPink
173-
$0.font = .systemFont(ofSize: 14, weight: .medium)
174-
$0.numberOfLines = 0
175-
$0.text = "Do not support relative layout for the time being\n暂不支持相对布局(正在开发中)"
176-
}
177-
178-
// specify `.maxWidth`
179-
UILabel().stack.maxWidth(UIScreen.main.bounds.width - 48).then {
180-
$0.textColor = .systemPink
181-
$0.font = .systemFont(ofSize: 14, weight: .medium)
182-
$0.numberOfLines = 0
183-
$0.text = "The subview may exceed the width/height of the parent view, and you need to specify the maximum width/height manually, add .maxWidth/.maxHeight after `.stack`\n子视图可能超过父视图的宽高,此时需要你手动设定最大宽度或最大高度"
184-
}
168+
UILabel().stack.then {
169+
$0.textColor = .systemPink
170+
$0.font = .systemFont(ofSize: 14, weight: .medium)
171+
$0.numberOfLines = 0
172+
$0.text = "Do not support relative layout for the time being\n暂不支持相对布局(正在开发中)"
173+
}
174+
175+
// specify `.maxWidth`
176+
UILabel().stack.maxWidth(UIScreen.main.bounds.width - 48).then {
177+
$0.textColor = .systemPink
178+
$0.font = .systemFont(ofSize: 14, weight: .medium)
179+
$0.numberOfLines = 0
180+
$0.text = "The subview may exceed the width/height of the parent view, and you need to specify the maximum width/height manually, add .maxWidth/.maxHeight after `.stack`\n子视图可能超过父视图的宽高,此时需要你手动设定最大宽度或最大高度"
185181
}
186182
}
187183
Spacer(length: 12)

README.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,24 @@ VStackView(padding: UIEdgeInsets)
3636
### Subview size is fixed
3737

3838
```swift
39-
logoView.stack.size(CGSize)
39+
logoView.stack.size(CGSize?)
4040
```
4141

4242
### Min or Max width/height
4343

4444
```swift
45-
briefLabel.stack.minWidth(CGFloat).maxWidth(CGFloat)
45+
briefLabel.stack.minWidth(CGFloat?)
46+
.maxWidth(CGFloat?)
47+
.minHeight(CGFloat?)
48+
.maxHeight(CGFloat?)
4649
```
4750

4851
### Offset
4952

5053
```swift
51-
briefLabel.stack.offset(CGPoint)
54+
briefLabel.stack.offset(CGPoint?)
55+
.offset(x: CGFloat?)
56+
.offset(y: CGFloat?)
5257
```
5358

5459
### SizeToFit
@@ -85,10 +90,10 @@ VStackView {
8590

8691
```swift
8792
// update text
88-
briefLabel.text = "Bump version to 1.2.1"
93+
briefLabel.text = "Bump version to 1.2.2"
8994

9095
// stackContainer means any instance of HStackView or VStackView
91-
stackContainer.setNeedsLayout()
96+
stackContainer.setNeedsLayout() // or .sizeToFit()
9297
```
9398

9499
# 🤔

Sources/StackKit/HStackView.swift

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,11 @@ open class HStackView: UIView, StackView {
6262
}
6363

6464
public var contentSize: CGSize {
65-
let h = effectiveSubviews.map({ $0.frame }).reduce(CGRect.zero) { result, rect in
66-
result.union(rect)
67-
}.width
68-
let w = effectiveSubviews.map({ $0.bounds }).reduce(CGRect.zero) { result, rect in
69-
result.union(rect)
70-
}.height
71-
return CGSize(width: h + paddingRight, height: w + paddingVertically)
65+
let width = effectiveSubviews.map({ $0.frame }).reduce(CGRect.zero, { $0.union($1) }).width
66+
let height = effectiveSubviews.map({ $0.bounds.height }).max() ?? 0
67+
68+
let offsetXLength = effectiveSubviews.map({ $0.frame.minX }).filter({ $0 < 0 }).min() ?? 0
69+
return CGSize(width: width + paddingRight + offsetXLength, height: height + paddingVertically)
7270
}
7371

7472
open func hideIfNoEffectiveViews() {
@@ -165,11 +163,12 @@ extension HStackView {
165163
}
166164
}
167165

168-
guard let offset = subview._stackKit_offset else {
169-
continue
166+
if let offsetX = subview._stackKit_offsetX {
167+
subview.frame.origin.x += offsetX
168+
}
169+
if let offsetY = subview._stackKit_offsetY {
170+
subview.frame.origin.y += offsetY
170171
}
171-
subview.frame.origin.x += offset.x
172-
subview.frame.origin.y += offset.y
173172
}
174173
}
175174

Sources/StackKit/UIView+StackKit/UIView+FitSize.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ extension UIView {
149149
var height: CGFloat?
150150

151151
var cgSize: CGSize {
152-
CGSize(width: width ?? 0, height: height ?? 0)
152+
CGSize(width: ceil(width ?? 0), height: ceil(height ?? 0))
153153
}
154154
}
155155

Sources/StackKit/UIView+StackKit/UIView+StackKitCompatibleProvider.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,20 @@ extension StackKitCompatible where Base: UIView {
1515

1616
@discardableResult
1717
public func offset(_ value: CGPoint?) -> Self {
18-
view._stackKit_offset = value
18+
view._stackKit_offsetX = value?.x
19+
view._stackKit_offsetY = value?.y
20+
return self
21+
}
22+
23+
@discardableResult
24+
public func offset(x value: CGFloat?) -> Self {
25+
view._stackKit_offsetX = value
26+
return self
27+
}
28+
29+
@discardableResult
30+
public func offset(y value: CGFloat?) -> Self {
31+
view._stackKit_offsetY = value
1932
return self
2033
}
2134

Lines changed: 24 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import UIKit
22

33
struct _UIView_StackKitKeys {
4-
static var offsetKey = "StackKit_offsetKey"
4+
static var offsetXKey = "StackKit_offsetXKey"
5+
static var offsetYKey = "StackKit_offsetYKey"
56

67
static var widthKey = "StackKit_widthKey"
78
static var heightKey = "StackKit_heightKey"
@@ -14,7 +15,8 @@ struct _UIView_StackKitKeys {
1415
}
1516

1617
protocol _UIView_StackKitProvider {
17-
var _stackKit_offset: CGPoint? { get set }
18+
var _stackKit_offsetX: CGFloat? { get set }
19+
var _stackKit_offsetY: CGFloat? { get set }
1820

1921
var _stackKit_width: CGFloat? { get set }
2022
var _stackKit_height: CGFloat? { get set }
@@ -28,71 +30,41 @@ protocol _UIView_StackKitProvider {
2830

2931
extension UIView: _UIView_StackKitProvider {
3032

31-
var _stackKit_offset: CGPoint? {
32-
get {
33-
guard let value = Runtime.getProperty(self, key: &_UIView_StackKitKeys.offsetKey) as? NSValue else {
34-
return nil
35-
}
36-
return value.cgPointValue
37-
}
38-
set {
39-
guard let newValue else {
40-
Runtime.setProperty(self, key: &_UIView_StackKitKeys.offsetKey, value: nil, policy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
41-
return
42-
}
43-
Runtime.setProperty(self, key: &_UIView_StackKitKeys.offsetKey, value: NSValue(cgPoint: newValue), policy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
44-
}
33+
var _stackKit_offsetX: CGFloat? {
34+
get { Runtime.getCGFloatProperty(self, key: &_UIView_StackKitKeys.offsetXKey) }
35+
set { Runtime.setCGFloatProperty(self, key: &_UIView_StackKitKeys.offsetXKey, newValue) }
36+
}
37+
38+
var _stackKit_offsetY: CGFloat? {
39+
get { Runtime.getCGFloatProperty(self, key: &_UIView_StackKitKeys.offsetYKey) }
40+
set { Runtime.setCGFloatProperty(self, key: &_UIView_StackKitKeys.offsetYKey, newValue) }
4541
}
4642

4743
var _stackKit_width: CGFloat? {
48-
get {
49-
Runtime.getCGFloatProperty(self, key: &_UIView_StackKitKeys.widthKey)
50-
}
51-
set {
52-
Runtime.setCGFloatProperty(self, key: &_UIView_StackKitKeys.widthKey, newValue)
53-
}
44+
get { Runtime.getCGFloatProperty(self, key: &_UIView_StackKitKeys.widthKey) }
45+
set { Runtime.setCGFloatProperty(self, key: &_UIView_StackKitKeys.widthKey, newValue) }
5446
}
5547
var _stackKit_height: CGFloat? {
56-
get {
57-
Runtime.getCGFloatProperty(self, key: &_UIView_StackKitKeys.heightKey)
58-
}
59-
set {
60-
Runtime.setCGFloatProperty(self, key: &_UIView_StackKitKeys.heightKey, newValue)
61-
}
48+
get { Runtime.getCGFloatProperty(self, key: &_UIView_StackKitKeys.heightKey) }
49+
set { Runtime.setCGFloatProperty(self, key: &_UIView_StackKitKeys.heightKey, newValue) }
6250
}
6351
var _stackKit_minWidth: CGFloat? {
64-
get {
65-
Runtime.getCGFloatProperty(self, key: &_UIView_StackKitKeys.minWidthKey)
66-
}
67-
set {
68-
Runtime.setCGFloatProperty(self, key: &_UIView_StackKitKeys.minWidthKey, newValue)
69-
}
52+
get { Runtime.getCGFloatProperty(self, key: &_UIView_StackKitKeys.minWidthKey) }
53+
set { Runtime.setCGFloatProperty(self, key: &_UIView_StackKitKeys.minWidthKey, newValue) }
7054
}
7155

7256
var _stackKit_maxWidth: CGFloat? {
73-
get {
74-
Runtime.getCGFloatProperty(self, key: &_UIView_StackKitKeys.maxWidthKey)
75-
}
76-
set {
77-
Runtime.setCGFloatProperty(self, key: &_UIView_StackKitKeys.maxWidthKey, newValue)
78-
}
57+
get { Runtime.getCGFloatProperty(self, key: &_UIView_StackKitKeys.maxWidthKey) }
58+
set { Runtime.setCGFloatProperty(self, key: &_UIView_StackKitKeys.maxWidthKey, newValue) }
7959
}
8060

8161
var _stackKit_minHeight: CGFloat? {
82-
get {
83-
Runtime.getCGFloatProperty(self, key: &_UIView_StackKitKeys.minHeightKey)
84-
}
85-
set {
86-
Runtime.setCGFloatProperty(self, key: &_UIView_StackKitKeys.minHeightKey, newValue)
87-
}
62+
get { Runtime.getCGFloatProperty(self, key: &_UIView_StackKitKeys.minHeightKey) }
63+
set { Runtime.setCGFloatProperty(self, key: &_UIView_StackKitKeys.minHeightKey, newValue) }
8864
}
8965

9066
var _stackKit_maxHeight: CGFloat? {
91-
get {
92-
Runtime.getCGFloatProperty(self, key: &_UIView_StackKitKeys.maxHeightKey)
93-
}
94-
set {
95-
Runtime.setCGFloatProperty(self, key: &_UIView_StackKitKeys.maxHeightKey, newValue)
96-
}
67+
get { Runtime.getCGFloatProperty(self, key: &_UIView_StackKitKeys.maxHeightKey) }
68+
set { Runtime.setCGFloatProperty(self, key: &_UIView_StackKitKeys.maxHeightKey, newValue) }
9769
}
9870
}

Sources/StackKit/VStackView.swift

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,11 @@ open class VStackView: UIView, StackView {
6262
}
6363

6464
public var contentSize: CGSize {
65-
let h = effectiveSubviews.map({ $0.frame }).reduce(CGRect.zero) { result, rect in
66-
result.union(rect)
67-
}.height
68-
let w = effectiveSubviews.map({ $0.bounds }).reduce(CGRect.zero) { result, rect in
69-
result.union(rect)
70-
}.width
71-
return CGSize(width: w + paddingHorizontally, height: h + paddingBottom)
65+
let width = effectiveSubviews.map({ $0.bounds.width }).max() ?? 0
66+
let height = effectiveSubviews.map({ $0.frame }).reduce(CGRect.zero, { $0.union($1) }).height
67+
68+
let offsetYLength: CGFloat = effectiveSubviews.map({ $0.frame.minY }).filter({ $0 < 0 }).min() ?? 0
69+
return CGSize(width: width + paddingHorizontally, height: height + paddingBottom + offsetYLength)
7270
}
7371

7472
open func hideIfNoEffectiveViews() {
@@ -165,11 +163,12 @@ extension VStackView {
165163
}
166164
}
167165

168-
guard let offset = subview._stackKit_offset else {
169-
continue
166+
if let offsetX = subview._stackKit_offsetX {
167+
subview.frame.origin.x += offsetX
168+
}
169+
if let offsetY = subview._stackKit_offsetY {
170+
subview.frame.origin.y += offsetY
170171
}
171-
subview.frame.origin.x += offset.x
172-
subview.frame.origin.y += offset.y
173172
}
174173
}
175174

0 commit comments

Comments
 (0)