Skip to content
This repository was archived by the owner on Dec 27, 2020. It is now read-only.

Commit 9b57859

Browse files
committed
styles
1 parent 58ccd47 commit 9b57859

12 files changed

+306
-129
lines changed

Examples/GridExamples macOS/ContentView.swift

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import SwiftUI
22
import Grid
33

44
struct ContentView: View {
5-
@State private var selection = 0
5+
@State private var selection = 1
66

77
var body: some View {
88
TabView(selection: $selection) {
@@ -11,23 +11,23 @@ struct ContentView: View {
1111
Text("One Column")
1212
}
1313
.tag(0)
14-
AutoColumnLayoutView()
15-
.tabItem {
16-
Text("Auto Column")
17-
}
18-
.tag(1)
19-
PerformanceLayoutView()
20-
.tabItem {
21-
Text("Performance")
22-
}
23-
.tag(2)
24-
BuilderLayoutView()
25-
.tabItem {
26-
Text("Builder")
27-
}
28-
.tag(2)
14+
// AutoColumnLayoutView()
15+
// .tabItem {
16+
// Text("Auto Column")
17+
// }
18+
// .tag(1)
19+
// PerformanceLayoutView()
20+
// .tabItem {
21+
// Text("Performance")
22+
// }
23+
// .tag(2)
24+
// BuilderLayoutView()
25+
// .tabItem {
26+
// Text("Builder")
27+
// }
28+
// .tag(2)
2929
}
30-
.frame(minWidth: 300, maxWidth: .infinity, maxHeight: .infinity)
30+
//.frame(maxWidth: .infinity, maxHeight: .infinity)
3131
.padding()
3232
}
3333
}

Examples/GridExamples/AutoColumnLayoutView.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@ import Grid
33

44
struct AutoColumnLayoutView: View {
55
var body: some View {
6-
ScrollView {
7-
Grid(0...100, minItemWidth: 120, itemHeight: 100) { number in
8-
Card(title: "\(number)")
9-
}
10-
.padding()
6+
Grid(0...100) { number in
7+
Card(title: "\(number)")
118
}
9+
.padding()
10+
.gridStyle(FixedColumnsGridStyle(columns: 5, itemHeight: 100))
1211
}
1312
}
1413

Examples/GridExamples/BuilderLayoutView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ struct BuilderLayoutView: View {
66
ScrollView {
77
VStack(alignment: .center) {
88
Section(header: Text("Section 1")) {
9-
Grid(itemHeight: 20) {
9+
Grid {
1010
ForEach(0...10, id: \.self) { _ in
1111
Rectangle()
1212
.foregroundColor(.random)
@@ -15,7 +15,7 @@ struct BuilderLayoutView: View {
1515
}
1616

1717
Section(header: Text("Section 2")) {
18-
Grid(itemHeight: 20) {
18+
Grid {
1919
ForEach(0...10, id: \.self) { _ in
2020
Rectangle()
2121
.foregroundColor(.random)

Examples/GridExamples/OneColumnLayoutView.swift

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@ import Grid
44
struct OneColumnLayoutView: View {
55
var body: some View {
66
GeometryReader { geometry in
7-
ScrollView(.vertical) {
8-
Grid(0...100, minItemWidth: geometry.size.width, itemHeight: 300) { number in
9-
Card(title: "\(number)")
10-
}
11-
.padding()
7+
///Grid(0...100, minItemWidth: geometry.size.width, itemHeight: 300) { number in
8+
Grid(0...100) { number in
9+
Card(title: "\(number)")
1210
}
11+
.padding()
12+
.gridStyle(SingleColumnGridStyle(itemHeight: 160))
1313
}
14-
1514
}
1615
}
1716

Examples/GridExamples/PerformanceLayoutView.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@ import Grid
33

44
struct PerformanceLayoutView: View {
55
var body: some View {
6-
ScrollView {
7-
Grid(0...5000, minItemWidth: 20, itemHeight: 20) { number in
8-
Rectangle()
9-
.foregroundColor(.random)
10-
}
6+
//, minItemWidth: 20, itemHeight: 20)
7+
Grid(0...5000) { number in
8+
Rectangle()
9+
.foregroundColor(.random)
1110
}
1211
}
1312
}

Sources/Grid/DefaultGridStyle.swift

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import SwiftUI
2+
3+
/// The default `Grid` style.
4+
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
5+
public struct DefaultGridStyle: GridStyle {
6+
public var padding = EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)
7+
8+
let minItemWidth: CGFloat = 100
9+
let itemHeight: CGFloat = 100
10+
let vSpacing: CGFloat = 8
11+
let hSpacing: CGFloat = 8
12+
13+
public init() {}
14+
15+
public func frameHeight(at index: Int, with geometry: GeometryProxy, itemsCount: Int) -> CGFloat? {
16+
self.itemHeight
17+
}
18+
public func frameWidth(at index: Int, with geometry: GeometryProxy, itemsCount: Int) -> CGFloat? {
19+
self.itemWidth(for: geometry, minItemWidth: self.minItemWidth, padding: self.padding, hSpacing: self.hSpacing)
20+
}
21+
22+
public func position(at index: Int, with geometry: GeometryProxy, itemsCount: Int) -> CGPoint {
23+
self.position(
24+
at: index,
25+
with: geometry,
26+
minItemWidth: self.minItemWidth,
27+
itemHeight: self.itemHeight,
28+
padding: self.padding,
29+
hSpacing: self.hSpacing
30+
)
31+
}
32+
33+
public func gridHeight(with geometry: GeometryProxy, itemsCount: Int) -> CGFloat {
34+
self.gridHeight(with: geometry, itemsCount: itemsCount, minItemWidth: self.minItemWidth, itemHeight: self.itemHeight, padding: self.padding, hSpacing: self.hSpacing)
35+
}
36+
37+
38+
@inlinable func availableWidth(with geometry: GeometryProxy, padding: EdgeInsets, hSpacing: CGFloat) -> CGFloat {
39+
let horizontalPadding = padding.leading + padding.trailing
40+
return geometry.size.width - horizontalPadding
41+
}
42+
43+
@inlinable func position(at index: Int, with geometry: GeometryProxy, minItemWidth: CGFloat, itemHeight: CGFloat, padding: EdgeInsets, hSpacing: CGFloat) -> CGPoint {
44+
let availableWidth = self.availableWidth(with: geometry, padding: padding, hSpacing: hSpacing)
45+
let columnCount = Int(availableWidth / minItemWidth)
46+
let row = index / max(1, columnCount)
47+
let itemIndexAtRow = index % max(1, columnCount)
48+
let itemWidth = self.itemWidth(for: geometry, minItemWidth: minItemWidth, padding: padding, hSpacing: hSpacing)
49+
let x = ((itemWidth / 2) + CGFloat(itemIndexAtRow) * itemWidth) + padding.leading
50+
let y = ((itemHeight / 2) + CGFloat(row) * itemHeight) + padding.top
51+
return CGPoint(x: x, y: y)
52+
}
53+
54+
@inlinable func itemWidth(for geometry: GeometryProxy, minItemWidth: CGFloat, padding: EdgeInsets, hSpacing: CGFloat) -> CGFloat {
55+
let availableWidth = self.availableWidth(with: geometry, padding: padding, hSpacing: hSpacing)
56+
return availableWidth / max(1.0, availableWidth / minItemWidth).rounded(.down)
57+
}
58+
59+
@inlinable func gridHeight(with geometry: GeometryProxy, itemsCount: Int, minItemWidth: CGFloat, itemHeight: CGFloat, padding: EdgeInsets, hSpacing: CGFloat) -> CGFloat {
60+
let availableWidth = self.availableWidth(with: geometry, padding: padding, hSpacing: hSpacing)
61+
let columnCount = Int(availableWidth / minItemWidth)
62+
let rowCount = Int((CGFloat(itemsCount) / max(1.0, CGFloat(columnCount))).rounded(.up))
63+
let verticalPadding = padding.top + padding.bottom
64+
return CGFloat(rowCount) * itemHeight + verticalPadding
65+
}
66+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import SwiftUI
2+
3+
/// Fixed columns `Grid` style.
4+
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
5+
public struct FixedColumnsGridStyle: GridStyle {
6+
public var padding = EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)
7+
8+
private let columns: Int
9+
private let itemHeight: CGFloat
10+
private let hSpacing: CGFloat
11+
private let vSpacing: CGFloat
12+
13+
public init(columns: Int, itemHeight: CGFloat, spacing: CGFloat = 8) {
14+
self.columns = columns
15+
self.itemHeight = itemHeight
16+
self.vSpacing = spacing
17+
self.hSpacing = spacing
18+
}
19+
20+
public init(columns: Int, itemHeight: CGFloat, hSpacing: CGFloat = 8, vSpacing: CGFloat = 8) {
21+
self.columns = columns
22+
self.itemHeight = itemHeight
23+
self.hSpacing = hSpacing
24+
self.vSpacing = vSpacing
25+
}
26+
27+
public func frameHeight(at index: Int, with geometry: GeometryProxy, itemsCount: Int) -> CGFloat? {
28+
self.itemHeight
29+
}
30+
public func frameWidth(at index: Int, with geometry: GeometryProxy, itemsCount: Int) -> CGFloat? {
31+
self.itemWidth(for: geometry, columns: self.columns, padding: self.padding, hSpacing: self.hSpacing)
32+
}
33+
34+
public func position(at index: Int, with geometry: GeometryProxy, itemsCount: Int) -> CGPoint {
35+
self.position(
36+
at: index,
37+
with: geometry,
38+
columns: self.columns,
39+
itemHeight: self.itemHeight,
40+
padding: self.padding,
41+
hSpacing: self.hSpacing,
42+
vSpacing: self.vSpacing
43+
)
44+
}
45+
46+
public func gridHeight(with geometry: GeometryProxy, itemsCount: Int) -> CGFloat {
47+
self.gridHeight(with: geometry, itemsCount: itemsCount, columns: self.columns, itemHeight: self.itemHeight, padding: self.padding, hSpacing: self.hSpacing)
48+
}
49+
50+
@inlinable func availableWidth(with geometry: GeometryProxy, padding: EdgeInsets, hSpacing: CGFloat) -> CGFloat {
51+
let horizontalPadding = padding.leading + padding.trailing
52+
return geometry.size.width - horizontalPadding
53+
}
54+
55+
@inlinable func position(at index: Int, with geometry: GeometryProxy, columns: Int, itemHeight: CGFloat, padding: EdgeInsets, hSpacing: CGFloat, vSpacing: CGFloat) -> CGPoint {
56+
let row = index / max(1, columns)
57+
let itemIndexAtRow = index % max(1, columns)
58+
let itemWidth = self.itemWidth(for: geometry, columns: columns, padding: padding, hSpacing: hSpacing)
59+
let x = ((itemWidth / 2) + CGFloat(itemIndexAtRow) * itemWidth) + padding.leading
60+
let y = ((itemHeight / 2) + CGFloat(row) * itemHeight) + padding.top + (CGFloat(row) * vSpacing)
61+
return CGPoint(x: x, y: y)
62+
}
63+
64+
@inlinable func itemWidth(for geometry: GeometryProxy, columns: Int, padding: EdgeInsets, hSpacing: CGFloat) -> CGFloat {
65+
let availableWidth = self.availableWidth(with: geometry, padding: padding, hSpacing: hSpacing)
66+
return availableWidth / CGFloat(columns)
67+
}
68+
69+
@inlinable func gridHeight(with geometry: GeometryProxy, itemsCount: Int, columns: Int, itemHeight: CGFloat, padding: EdgeInsets, hSpacing: CGFloat) -> CGFloat {
70+
let rowCount = Int((CGFloat(itemsCount) / max(1.0, CGFloat(columns))).rounded(.up))
71+
let verticalPadding = padding.top + padding.bottom
72+
return CGFloat(rowCount) * itemHeight + verticalPadding
73+
}
74+
}

Sources/Grid/Grid+Inits.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import SwiftUI
22

33
extension Grid {
4-
public init<Data: RandomAccessCollection>(_ data: Data, minItemWidth: CGFloat = 100, itemHeight: CGFloat = 100, spacing: CGFloat = 8, @ViewBuilder content: @escaping (Data.Element) -> Content) {
5-
self.init(items: data.map({ AnyView(content($0)) }), minItemWidth: minItemWidth, itemHeight: itemHeight, spacing: spacing)
4+
public init<Data: RandomAccessCollection>(_ data: Data, @ViewBuilder content: @escaping (Data.Element) -> Content) {
5+
self.items = data.map({ AnyView(content($0)) })
66
}
77

8-
public init<Data: RandomAccessCollection, ID, Item: View>(minItemWidth: CGFloat = 100, itemHeight: CGFloat = 100, spacing: CGFloat = 8, @ViewBuilder content: () -> Content) where Content == ForEach<Data, ID, Item> {
8+
public init<Data: RandomAccessCollection, ID, Item: View>(@ViewBuilder content: () -> Content) where Content == ForEach<Data, ID, Item> {
99
let views = content()
10-
self.init(items: views.data.map { AnyView(views.content($0)) }, minItemWidth: minItemWidth, itemHeight: itemHeight, spacing: spacing)
10+
self.items = views.data.map { AnyView(views.content($0)) }
1111
}
1212
}

Sources/Grid/Grid+Padding.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import SwiftUI
2+
3+
extension Grid {
4+
public func padding(_ length: CGFloat = 8) -> some View {
5+
self.environment(\.gridStyle.padding, EdgeInsets(top: length, leading: length, bottom: length, trailing: length))
6+
}
7+
8+
public func padding(_ insets: EdgeInsets) -> some View {
9+
self.environment(\.gridStyle.padding, insets)
10+
}
11+
12+
public func padding(_ edges: Edge.Set = .all, _ length: CGFloat? = nil) -> some View {
13+
var edgeInsets = EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)
14+
15+
if let length = length {
16+
if edges.contains(.all) || edges.contains(.top) || edges.contains(.vertical) {
17+
edgeInsets.top = length
18+
}
19+
if edges.contains(.all) || edges.contains(.leading) || edges.contains(.horizontal) {
20+
edgeInsets.leading = length
21+
}
22+
if edges.contains(.all) || edges.contains(.bottom) || edges.contains(.vertical) {
23+
edgeInsets.trailing = length
24+
}
25+
if edges.contains(.all) || edges.contains(.trailing) || edges.contains(.horizontal) {
26+
edgeInsets.trailing = length
27+
}
28+
}
29+
return self.environment(\.gridStyle.padding, edgeInsets)
30+
}
31+
}
32+
33+
34+
//struct GridPaddingKey: EnvironmentKey {
35+
// static let defaultValue: EdgeInsets = .init(top: 0, leading: 0, bottom: 0, trailing: 0)
36+
//}
37+
38+
//extension EnvironmentValues {
39+
// var gridPadding: EdgeInsets {
40+
// get {
41+
// return self[GridPaddingKey.self]
42+
// }
43+
// set {
44+
// self[GridPaddingKey.self] = newValue
45+
// }
46+
// }
47+
//}

Sources/Grid/Grid+Style.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import SwiftUI
2+
3+
/// A specification for the appearance of a `Grid`.
4+
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
5+
public protocol GridStyle {
6+
var padding: EdgeInsets { get set }
7+
8+
func frameHeight(at index: Int, with geometry: GeometryProxy, itemsCount: Int) -> CGFloat?
9+
func frameWidth(at index: Int, with geometry: GeometryProxy, itemsCount: Int) -> CGFloat?
10+
func position(at index: Int, with geometry: GeometryProxy, itemsCount: Int) -> CGPoint
11+
func gridHeight(with geometry: GeometryProxy, itemsCount: Int) -> CGFloat
12+
}
13+
14+
extension View {
15+
16+
/// Sets the style for `Grid` within the environment of `self`.
17+
public func gridStyle<S>(_ style: S) -> some View where S : GridStyle {
18+
self.environment(\.gridStyle, style)
19+
}
20+
21+
}
22+
23+
struct GridStyleKey: EnvironmentKey {
24+
static let defaultValue: GridStyle = DefaultGridStyle()
25+
}
26+
27+
extension EnvironmentValues {
28+
var gridStyle: GridStyle {
29+
get {
30+
return self[GridStyleKey.self]
31+
}
32+
set {
33+
self[GridStyleKey.self] = newValue
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)