Skip to content

Commit

Permalink
Merge pull request #34 from iWECon/wrap-stack
Browse files Browse the repository at this point in the history
WrapStack Support
  • Loading branch information
iWECon authored Jul 21, 2023
2 parents 1a44b09 + 874e675 commit 6ad4e5f
Show file tree
Hide file tree
Showing 10 changed files with 483 additions and 15 deletions.
4 changes: 4 additions & 0 deletions Demo/Demo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
080677C628BE7D8B00000E16 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 080677C528BE7D8B00000E16 /* ViewController.swift */; };
080677C828BE7DA400000E16 /* WrapStackDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 080677C728BE7DA400000E16 /* WrapStackDemoViewController.swift */; };
0815C093292A2B37001655C6 /* Preview1ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0815C092292A2B37001655C6 /* Preview1ViewController.swift */; };
083B50042A36C54100778E58 /* WrapStackLayerDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 083B50032A36C54100778E58 /* WrapStackLayerDemoViewController.swift */; };
08A24B8428E49A9600CDD7E2 /* LookinServer in Frameworks */ = {isa = PBXBuildFile; productRef = 08A24B8328E49A9600CDD7E2 /* LookinServer */; };
08E16CD9289ABA1C0019D7CB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08E16CD8289ABA1C0019D7CB /* AppDelegate.swift */; };
08E16CDB289ABA1C0019D7CB /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08E16CDA289ABA1C0019D7CB /* SceneDelegate.swift */; };
Expand All @@ -25,6 +26,7 @@
080677C528BE7D8B00000E16 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
080677C728BE7DA400000E16 /* WrapStackDemoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrapStackDemoViewController.swift; sourceTree = "<group>"; };
0815C092292A2B37001655C6 /* Preview1ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preview1ViewController.swift; sourceTree = "<group>"; };
083B50032A36C54100778E58 /* WrapStackLayerDemoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrapStackLayerDemoViewController.swift; sourceTree = "<group>"; };
08E16CD5289ABA1C0019D7CB /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; };
08E16CD8289ABA1C0019D7CB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
08E16CDA289ABA1C0019D7CB /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -77,6 +79,7 @@
0815C092292A2B37001655C6 /* Preview1ViewController.swift */,
08E16CDC289ABA1C0019D7CB /* HVStackDemoViewController.swift */,
080677C728BE7DA400000E16 /* WrapStackDemoViewController.swift */,
083B50032A36C54100778E58 /* WrapStackLayerDemoViewController.swift */,
08E16CDE289ABA1C0019D7CB /* Main.storyboard */,
08E16CE1289ABA1D0019D7CB /* Assets.xcassets */,
08E16CE3289ABA1D0019D7CB /* LaunchScreen.storyboard */,
Expand Down Expand Up @@ -185,6 +188,7 @@
08E16CDD289ABA1C0019D7CB /* HVStackDemoViewController.swift in Sources */,
080677C828BE7DA400000E16 /* WrapStackDemoViewController.swift in Sources */,
08E16CD9289ABA1C0019D7CB /* AppDelegate.swift in Sources */,
083B50042A36C54100778E58 /* WrapStackLayerDemoViewController.swift in Sources */,
08E16CDB289ABA1C0019D7CB /* SceneDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
32 changes: 28 additions & 4 deletions Demo/Demo/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,40 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="21" translatesAutoresizingMaskIntoConstraints="NO" id="M84-Lf-Gfo">
<rect key="frame" x="135" y="375.5" width="144" height="145.5"/>
<rect key="frame" x="132.5" y="347.5" width="149.5" height="201"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7Tv-fS-6AC">
<rect key="frame" x="0.0" y="0.0" width="144" height="34.5"/>
<rect key="frame" x="0.0" y="0.0" width="149.5" height="34.5"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Preview 1"/>
<connections>
<segue destination="tKx-sr-SVC" kind="show" id="uEI-YO-OWR"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="06f-Ws-ezl">
<rect key="frame" x="0.0" y="55.5" width="144" height="34.5"/>
<rect key="frame" x="0.0" y="55.5" width="149.5" height="34.5"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="H/VStackView"/>
<connections>
<segue destination="hGA-TO-DpM" kind="show" id="CVz-1t-QBY"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Dpb-UY-wFq">
<rect key="frame" x="0.0" y="111" width="144" height="34.5"/>
<rect key="frame" x="0.0" y="111" width="149.5" height="34.5"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="WrapStackView"/>
<connections>
<segue destination="qy3-1p-iRp" kind="show" id="npM-Qe-FDz"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="l2O-iF-vtx">
<rect key="frame" x="0.0" y="166.5" width="149.5" height="34.5"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="WrapStackLayer"/>
<connections>
<segue destination="mJ5-v7-Oak" kind="show" id="X1E-c0-Wwr"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
Expand Down Expand Up @@ -126,6 +134,22 @@
</objects>
<point key="canvasLocation" x="3648" y="855"/>
</scene>
<!--WrapStackLayer-->
<scene sceneID="Wzu-Wo-ZdA">
<objects>
<viewController id="mJ5-v7-Oak" customClass="WrapStackLayerDemoViewController" customModule="Demo" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="CMD-q7-Sic">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<viewLayoutGuide key="safeArea" id="0ho-z9-azb"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</view>
<navigationItem key="navigationItem" title="WrapStackLayer" largeTitleDisplayMode="never" id="Qy7-7k-TEV"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="fjO-n9-FWN" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="3648" y="1550"/>
</scene>
</scenes>
<resources>
<systemColor name="systemBackgroundColor">
Expand Down
64 changes: 63 additions & 1 deletion Demo/Demo/WrapStackDemoViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,76 @@ import UIKit
import StackKit

class WrapStackDemoViewController: UIViewController {

let fixedWrapStackView = WrapStackView(
itemSize: .fixed(CGSize(width: 30, height: 30)),
contentInsets: UIEdgeInsets(top: 20, left: 14, bottom: 20, right: 14),
itemSpacing: 4,
lineSpacing: 10
)

let adaptiveWrapStackView = WrapStackView(
itemSize: .adaptive(column: 6),
contentInsets: UIEdgeInsets(top: 20, left: 14, bottom: 20, right: 14),
itemSpacing: 10,
lineSpacing: 4
)

let autoWrapStackView = WrapStackView(
itemSize: .auto,
contentInsets: UIEdgeInsets(top: 20, left: 14, bottom: 20, right: 14),
itemSpacing: 10,
lineSpacing: 10
)

override func viewDidLoad() {
super.viewDidLoad()

// Do any additional setup after loading the view.
let widths: [CGFloat] = [20, 30, 50, 120, 40, 230, 50, 60, 10]
fixedWrapStackView.addContent {
for _ in (0 ... 3) {
makeUIView().stack.then { $0.frame.size = CGSize(width: widths.randomElement() ?? 10, height: 30) }
}
}
view.addSubview(fixedWrapStackView)

adaptiveWrapStackView.addContent {
for _ in (0 ... 11) {
makeUIView().stack.then { $0.frame.size = CGSize(width: widths.randomElement() ?? 10, height: 30) }
}
}
view.addSubview(adaptiveWrapStackView)

autoWrapStackView.addContent {
for _ in (0 ... 9) {
makeUIView().stack.then { $0.frame.size = CGSize(width: widths.randomElement() ?? 10, height: 30) }
}
makeUIView().stack.size(50, 30)
makeUIView().stack.size(60, 30)
makeUIView().stack.size(20, 30)
makeUIView().stack.size(10, 30)
}
view.addSubview(autoWrapStackView)
}


private func makeUIView() -> UIView {
let v = UIView()
let red: CGFloat = CGFloat((0 ... 255).randomElement() ?? 0) / 255
let green: CGFloat = CGFloat((0 ... 255).randomElement() ?? 0) / 255
let blue: CGFloat = CGFloat((0 ... 255).randomElement() ?? 0) / 255
v.backgroundColor = UIColor.init(red: red, green: green, blue: blue, alpha: 1)
return v
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

fixedWrapStackView.pin.top(120).horizontally().sizeToFit(.content)
adaptiveWrapStackView.pin.top(to: fixedWrapStackView.edge.bottom).marginTop(50).horizontally().sizeToFit(.width)
autoWrapStackView.pin.top(to: adaptiveWrapStackView.edge.bottom).marginTop(50).horizontally().sizeToFit(.width)
}

/*
// MARK: - Navigation

Expand Down
92 changes: 92 additions & 0 deletions Demo/Demo/WrapStackLayerDemoViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//
// WrapStackLayerDemoViewController.swift
// Demo
//
// Created by i on 2023/6/12.
//

import UIKit
import StackKit
import PinLayout

extension WrapStackLayer: SizeCalculable { }

class WrapStackLayerDemoViewController: UIViewController {

let fixedWrapStackLayer = WrapStackLayer(
itemSize: .fixed(CGSize(width: 30, height: 30)),
contentInsets: UIEdgeInsets(top: 20, left: 14, bottom: 20, right: 14),
itemSpacing: 4,
lineSpacing: 10
)

let adaptiveWrapStackLayer = WrapStackLayer(
itemSize: .adaptive(column: 6),
contentInsets: UIEdgeInsets(top: 20, left: 14, bottom: 20, right: 14),
itemSpacing: 10,
lineSpacing: 4
)

let autoWrapStackLayer = WrapStackLayer(
itemSize: .auto,
contentInsets: UIEdgeInsets(top: 20, left: 14, bottom: 20, right: 14),
itemSpacing: 10,
lineSpacing: 10
)

override func viewDidLoad() {
super.viewDidLoad()

// Do any additional setup after loading the view.
let widths: [CGFloat] = [20, 30, 50, 120, 40, 230, 50, 60, 10]
fixedWrapStackLayer.addContent {
for _ in (0 ... 20) {
makeUIView(size: CGSize(width: widths.randomElement() ?? 10, height: 30))
}
}
view.layer.addSublayer(fixedWrapStackLayer)

adaptiveWrapStackLayer.addContent {
for _ in (0 ... 11) {
makeUIView(size: CGSize(width: widths.randomElement() ?? 10, height: 30))
}
}
view.layer.addSublayer(adaptiveWrapStackLayer)

autoWrapStackLayer.addContent {
for _ in (0 ... 11) {
makeUIView(size: CGSize(width: widths.randomElement() ?? 10, height: 30))
}
}
view.layer.addSublayer(autoWrapStackLayer)
}

private func makeUIView(size: CGSize) -> CALayer {
let v = CALayer()
let red: CGFloat = CGFloat((0 ... 255).randomElement() ?? 0) / 255
let green: CGFloat = CGFloat((0 ... 255).randomElement() ?? 0) / 255
let blue: CGFloat = CGFloat((0 ... 255).randomElement() ?? 0) / 255
v.backgroundColor = UIColor.init(red: red, green: green, blue: blue, alpha: 1).cgColor
v.frame.size = size
return v
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

fixedWrapStackLayer.pin.top(120).maxWidth(220).sizeToFit(.width)
adaptiveWrapStackLayer.pin.top(to: fixedWrapStackLayer.edge.bottom).marginTop(50).horizontally().sizeToFit(.width)
autoWrapStackLayer.pin.top(to: adaptiveWrapStackLayer.edge.bottom).marginTop(50).horizontally().sizeToFit(.width)
}

/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/

}
1 change: 1 addition & 0 deletions Sources/StackKit/Enums.swift
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ public enum WrapStackHorizontalAlignment {
public enum WrapStackItemSize {
case fixed(_ size: CGSize)
case adaptive(column: Int)
case auto
}

public enum WrapStackLayout {
Expand Down
3 changes: 1 addition & 2 deletions Sources/StackKit/Layer/HStackLayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ open class HStackLayer: CALayer, StackLayer {
}

open override func preferredFrameSize() -> CGSize {
setNeedsLayout()
setNeedsDisplay()
layoutSublayers()
return contentSize
}

Expand Down
4 changes: 1 addition & 3 deletions Sources/StackKit/Layer/VStackLayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,7 @@ open class VStackLayer: CALayer, StackLayer {
}

public func sizeThatFits(_ size: CGSize) -> CGSize {
setNeedsLayout()
layoutIfNeeded()

layoutSublayers()
return contentSize
}

Expand Down
1 change: 1 addition & 0 deletions Sources/StackKit/StackKitResultBuilders.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,4 @@ extension _StackKitLayerContentResultBuilder {

@resultBuilder public struct _StackKitVStackLayerContentResultBuilder: _StackKitLayerContentResultBuilder { }
@resultBuilder public struct _StackKitHStackLayerContentResultBuilder: _StackKitLayerContentResultBuilder { }
@resultBuilder public struct _StackKitWrapStackLayerContentResultBuilder: _StackKitLayerContentResultBuilder { }
Loading

0 comments on commit 6ad4e5f

Please sign in to comment.