@@ -2,38 +2,61 @@ import SwiftUI
2
2
3
3
/// A view that arranges its children in a grid.
4
4
@available ( iOS 13 . 0 , OSX 10 . 15 , * )
5
- public struct Grid < Data, Content> : View where Data: RandomAccessCollection , Data. Element: Identifiable , Content : View {
6
- public typealias Item = Data . Element . IdentifiedValue
7
- private let data : [ Item ]
8
- private let minimumItemWidth : Length
9
- private let spacing : Length
10
- private let content : ( Item ) -> Content
5
+ public struct Grid < Data, Content> : View where Data: RandomAccessCollection , Content : View {
6
+ private let data : [ Data . Element ]
7
+ private let minimumItemWidth : CGFloat
8
+ private let spacing : CGFloat
9
+ private let content : ( Data . Element ) -> Content
11
10
12
11
public var body : some View {
13
12
GeometryReader { geometry in
14
13
ScrollView {
15
- VStack ( spacing: self . spacing) {
16
- ForEach ( 0 ..< Int ( ( Length ( self . data . count ) / max ( 1.0 , geometry. size . width / self . minimumItemWidth ) . rounded ( . down ) ) . rounded ( . up ) ) ) { rowIndex in
14
+ VStack ( alignment : . leading , spacing: self . spacing) {
15
+ ForEach ( 0 ..< self . rowCount ( with : geometry) , id : \ . self ) { rowIndex in
17
16
HStack ( spacing: self . spacing) {
18
- ForEach ( 0 ..< Int ( geometry. size. width / self . minimumItemWidth) ) { columnIndex in
19
- if rowIndex * max( 1 , Int ( geometry. size. width / self . minimumItemWidth) ) + columnIndex <= self . data. count - 1 {
20
- self . content ( self . data [ rowIndex * max( 1 , Int ( geometry. size. width / self . minimumItemWidth) ) + columnIndex] )
21
- } else {
22
- Rectangle ( ) . foregroundColor ( . clear)
23
- }
17
+ ForEach ( 0 ..< self . columnCount ( with: geometry) , id: \. self) { ( columnIndex: Int ) -> Content ? in
18
+ self . item ( with: geometry, rowIndex: rowIndex, columnIndex: columnIndex)
19
+ }
20
+ ForEach ( 0 ..< self . emptyElementsCount ( geometry: geometry, row: rowIndex) , id: \. self) { _ in
21
+ Spacer ( )
24
22
}
25
23
}
26
24
}
27
- . clipped ( )
28
25
}
29
26
. padding ( )
30
27
}
28
+
31
29
}
32
-
33
30
}
34
31
35
- public init ( _ data: Data , minimumItemWidth: Length = 300 , spacing: Length = 8 , content: @escaping ( Item ) -> Content ) {
36
- self . data = data. map { $0. identifiedValue }
32
+ func emptyElementsCount( geometry: GeometryProxy , row: Int ) -> Int {
33
+ let isLastRow = rowCount ( with: geometry) - 1 == row
34
+ let possibleItemsCount = rowCount ( with: geometry) * columnCount( with: geometry)
35
+ return isLastRow ? possibleItemsCount % data. count : 0
36
+ }
37
+
38
+ func rowCount( with geometry: GeometryProxy ) -> Int {
39
+ Int ( ( CGFloat ( self . data. count) / max( 1.0 , geometry. size. width / self . minimumItemWidth) . rounded ( . down) ) . rounded ( . up) )
40
+ }
41
+
42
+ func columnCount( with geometry: GeometryProxy ) -> Int {
43
+ Int ( geometry. size. width / self . minimumItemWidth)
44
+ }
45
+
46
+ func itemIndex( with geometry: GeometryProxy , rowIndex: Int , columnIndex: Int ) -> Int {
47
+ rowIndex * max( 1 , Int ( geometry. size. width / self . minimumItemWidth) ) + columnIndex
48
+ }
49
+
50
+ func item( with geometry: GeometryProxy , rowIndex: Int , columnIndex: Int ) -> Content ? {
51
+ if self . itemIndex ( with: geometry, rowIndex: rowIndex, columnIndex: columnIndex) <= self . data. count - 1 {
52
+ return self . content ( self . data [ self . itemIndex ( with: geometry, rowIndex: rowIndex, columnIndex: columnIndex) ] )
53
+ } else {
54
+ return nil
55
+ }
56
+ }
57
+
58
+ public init ( _ data: Data , minimumItemWidth: CGFloat = 300 , spacing: CGFloat = 8 , content: @escaping ( Data . Element ) -> Content ) {
59
+ self . data = data. map { $0 }
37
60
self . content = content
38
61
self . spacing = spacing
39
62
self . minimumItemWidth = minimumItemWidth
@@ -43,7 +66,9 @@ public struct Grid<Data, Content> : View where Data: RandomAccessCollection, Dat
43
66
#if DEBUG
44
67
struct Grid_Previews : PreviewProvider {
45
68
static var previews : some View {
46
- Text ( " 123 " )
69
+ Grid ( 0 ... 100 ) {
70
+ Text ( " \( $0) " )
71
+ }
47
72
}
48
73
}
49
74
#endif
0 commit comments