Skip to content

Commit 860e93e

Browse files
committed
Improvements
1 parent 599c97a commit 860e93e

File tree

9 files changed

+85
-50
lines changed

9 files changed

+85
-50
lines changed

README.md

Lines changed: 78 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -99,59 +99,112 @@ HFlow(itemSpacing: 4, rowSpacing: 20) {
9999

100100
![HFlow](Resources/hflow-spacing.png)
101101

102-
## Justified
102+
## Distribute items
103103

104-
Justify by stretching items, the spaces between them, or both.
104+
Distribute items evenly by minimizing the empty spaces left in each row.
105+
Implements the Knuth-Plass line breaking algorithm.
105106

106107
```swift
107-
HFlow(justification: .stretchItems) {
108+
HFlow(distributeItemsEvenly: true) {
108109
ForEach(colors, id: \.description) { color in
109110
RoundedRectangle(cornerRadius: 10)
110111
.fill(color.gradient)
111-
.frame(height: 50)
112-
.frame(minWidth: 35)
112+
.frame(width: 65, height: 50)
113113
}
114114
}
115-
.frame(width: 300)
115+
.frame(width: 300, alignment: .leading)
116116
```
117117

118-
![HFlow](Resources/hflow-justified.png)
119-
120-
---
118+
![HFlow](Resources/hflow-distributed.png)
121119

122-
Distribute items evenly by minimizing the empty spaces left in each row.
123-
Implements the Knuth-Plass line breaking algorithm.
120+
## Justified
124121

125122
```swift
126-
HFlow(distributeItemsEvenly: true) {
123+
HFlow(justified: true) {
127124
ForEach(colors, id: \.description) { color in
128125
RoundedRectangle(cornerRadius: 10)
129126
.fill(color.gradient)
130-
.frame(width: 65, height: 50)
127+
.frame(width: 50, height: 50)
131128
}
132129
}
133-
.frame(width: 300, alignment: .leading)
130+
.frame(width: 300)
134131
```
135132

136-
![HFlow](Resources/hflow-distributed.png)
133+
![HFlow](Resources/hflow-justified.png)
134+
135+
## Flexibility
136+
137+
```swift
138+
HFlow { // distributes flexible items proportionally
139+
RoundedRectangle(cornerRadius: 10)
140+
.fill(.red)
141+
.frame(minWidth: 50, maxWidth: .infinity)
142+
.frame(height: 50)
143+
.flexibility(.minimum) // takes as little space as possible, rigid
144+
RoundedRectangle(cornerRadius: 10)
145+
.fill(.green)
146+
.frame(minWidth: 50, maxWidth: .infinity)
147+
.frame(height: 50)
148+
.flexibility(.natural) // expands
149+
RoundedRectangle(cornerRadius: 10)
150+
.fill(.blue)
151+
.frame(minWidth: 50, maxWidth: .infinity)
152+
.frame(height: 50)
153+
.flexibility(.natural) // expands
154+
RoundedRectangle(cornerRadius: 10)
155+
.fill(.yellow)
156+
.frame(minWidth: 50, maxWidth: .infinity)
157+
.frame(height: 50) // takes as much space as possible
158+
.flexibility(.maximum)
159+
}
160+
.frame(width: 300)
161+
```
137162

138-
---
163+
![HFlow](Resources/hflow-flexibility.png)
139164

140-
Distribute and justify for visually pleasing UI.
165+
## Line breaks
141166

142167
```swift
143-
HFlow(justification: .stretchItems, distributeItemsEvenly: true) {
144-
ForEach(colors, id: \.description) { color in
145-
RoundedRectangle(cornerRadius: 10)
146-
.fill(color.gradient)
147-
.frame(height: 50)
148-
.frame(minWidth: 60)
149-
}
168+
HFlow {
169+
RoundedRectangle(cornerRadius: 10)
170+
.fill(.red)
171+
.frame(width: 50, height: 50)
172+
RoundedRectangle(cornerRadius: 10)
173+
.fill(.green)
174+
.frame(width: 50, height: 50)
175+
RoundedRectangle(cornerRadius: 10)
176+
.fill(.blue)
177+
.frame(width: 50, height: 50)
178+
LineBreak()
179+
RoundedRectangle(cornerRadius: 10)
180+
.fill(.yellow)
181+
.frame(width: 50, height: 50)
182+
}
183+
.frame(width: 300)
184+
```
185+
186+
![HFlow](Resources/hflow-linebreak.png)
187+
188+
```swift
189+
HFlow {
190+
RoundedRectangle(cornerRadius: 10)
191+
.fill(.red)
192+
.frame(width: 50, height: 50)
193+
RoundedRectangle(cornerRadius: 10)
194+
.fill(.green)
195+
.frame(width: 50, height: 50)
196+
.startInNewLine()
197+
RoundedRectangle(cornerRadius: 10)
198+
.fill(.blue)
199+
.frame(width: 50, height: 50)
200+
RoundedRectangle(cornerRadius: 10)
201+
.fill(.yellow)
202+
.frame(width: 50, height: 50)
150203
}
151204
.frame(width: 300)
152205
```
153206

154-
![HFlow](Resources/hflow-justified-and-distributed.png)
207+
![HFlow](Resources/hflow-newline.png)
155208

156209
## RTL
157210

Resources/hflow-flexibility.png

2.54 KB
Loading
-34.2 KB
Binary file not shown.

Resources/hflow-justified.png

-28.3 KB
Loading

Resources/hflow-linebreak.png

2.58 KB
Loading

Resources/hflow-newline.png

2.56 KB
Loading

Sources/Flow/Example/ContentView.swift

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ struct ContentView: View {
77
@State private var height: CGFloat = 400
88
@State private var itemSpacing: CGFloat? = nil
99
@State private var lineSpacing: CGFloat? = nil
10-
@State private var justified: Justified = .none
10+
@State private var justified: Bool = false
1111
@State private var horizontalAlignment: HAlignment = .leading
1212
@State private var verticalAlignment: VAlignment = .top
1313
@State private var distributeItemsEvenly: Bool = false
@@ -75,7 +75,7 @@ struct ContentView: View {
7575
stepper("Line", $lineSpacing)
7676
}
7777
Section(header: Text("Extras")) {
78-
picker($justified, style: .inline)
78+
Toggle("Justified", isOn: $justified)
7979
Toggle("Distibute evenly", isOn: $distributeItemsEvenly.animation())
8080
}
8181
}
@@ -134,7 +134,7 @@ struct ContentView: View {
134134
verticalAlignment: verticalAlignment.value,
135135
horizontalSpacing: itemSpacing,
136136
verticalSpacing: lineSpacing,
137-
justification: justified.justification,
137+
justified: justified,
138138
distributeItemsEvenly: distributeItemsEvenly
139139
)
140140
)
@@ -145,7 +145,7 @@ struct ContentView: View {
145145
verticalAlignment: verticalAlignment.value,
146146
horizontalSpacing: lineSpacing,
147147
verticalSpacing: itemSpacing,
148-
justification: justified.justification,
148+
justified: justified,
149149
distributeItemsEvenly: distributeItemsEvenly
150150
)
151151
)
@@ -160,24 +160,6 @@ enum Contents: String, CustomStringConvertible, CaseIterable {
160160
var description: String { rawValue }
161161
}
162162

163-
enum Justified: String, CustomStringConvertible, CaseIterable {
164-
case none = "no justification"
165-
case stretchItems = "stretch items"
166-
case stretchSpaces = "stretch spaces"
167-
case stretchItemsAndSpaces = "stretch both"
168-
169-
var description: String { rawValue }
170-
171-
var justification: Justification? {
172-
switch self {
173-
case .none: nil
174-
case .stretchItems: .stretchItems
175-
case .stretchSpaces: .stretchSpaces
176-
case .stretchItemsAndSpaces: .stretchItemsAndSpaces
177-
}
178-
}
179-
}
180-
181163
#Preview {
182164
ContentView()
183165
}

Sources/Flow/Internal/LineBreaking.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ func sizes(of items: IndexedLineBreakingInput, availableSpace: CGFloat) -> SizeC
162162
return nil
163163
}
164164
// Calculate total size
165-
var totalSizeOfItems = items.sum(of: \.element.size.lowerBound) + items.dropFirst().sum(of: \.element.spacing)
165+
let totalSizeOfItems = items.sum(of: \.element.size.lowerBound) + items.dropFirst().sum(of: \.element.spacing)
166166
if totalSizeOfItems > availableSpace {
167167
return nil
168168
}

Sources/Flow/Support.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ public struct LineBreak: View {
8585

8686
extension View {
8787
/// Allows flow layout elements to be started on new lines, allowing precise control over line breaking.
88-
public func startInNewLine() -> some View {
89-
layoutValue(key: ShouldStartInNewLineLayoutValueKey.self, value: true)
88+
public func startInNewLine(_ enabled: Bool = true) -> some View {
89+
layoutValue(key: ShouldStartInNewLineLayoutValueKey.self, value: enabled)
9090
}
9191

9292
/// Allows modifying the flexibility behavior of views so that flow can layout them accordingly.

0 commit comments

Comments
 (0)