27
27
28
28
import UIKit
29
29
30
+
30
31
// MARK: - 🦆 Type definitions
31
32
32
33
/// An abstract protocol that defines an alignment.
33
34
protocol Alignment { }
34
35
35
- /// Defines an alignment for UI elements.
36
+ /// Defines a horizontal alignment for UI elements.
36
37
public enum HorizontalAlignment : Alignment {
37
38
case left
38
- case justified
39
39
case right
40
+ case leading
41
+ case trailing
42
+ case justified
40
43
}
41
44
42
45
/// Defines a vertical alignment for UI elements.
@@ -46,6 +49,14 @@ public enum VerticalAlignment: Alignment {
46
49
case bottom
47
50
}
48
51
52
+ /// A horizontal alignment used internally by `AlignedCollectionViewFlowLayout`
53
+ /// to layout the items, after resolving layout direction specifics.
54
+ private enum EffectiveHorizontalAlignment : Alignment {
55
+ case left
56
+ case right
57
+ case justified
58
+ }
59
+
49
60
/// Describes an axis with respect to which items can be aligned.
50
61
private struct AlignmentAxis < A: Alignment > {
51
62
@@ -59,6 +70,9 @@ private struct AlignmentAxis<A: Alignment> {
59
70
}
60
71
61
72
73
+
74
+ // MARK: - Flow Layout
75
+
62
76
/// A `UICollectionViewFlowLayout` subclass that gives you control
63
77
/// over the horizontal and vertical alignment of the cells.
64
78
/// You can use it to align the cells like words in a left- or right-aligned text
@@ -70,15 +84,57 @@ open class AlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
70
84
/// Determines how the cells are horizontally aligned in a row.
71
85
/// - Note: The default is `.justified`.
72
86
public var horizontalAlignment : HorizontalAlignment = . justified
73
-
87
+
74
88
/// Determines how the cells are vertically aligned in a row.
75
89
/// - Note: The default is `.center`.
76
90
public var verticalAlignment : VerticalAlignment = . center
91
+
92
+ /// The `horizontalAlignment` with its layout direction specifics resolved,
93
+ /// i.e. `.leading` and `.trailing` alignments are mapped to `.left` or `right`,
94
+ /// depending on the current layout direction.
95
+ fileprivate var effectiveHorizontalAlignment : EffectiveHorizontalAlignment {
96
+
97
+ var trivialMapping : [ HorizontalAlignment : EffectiveHorizontalAlignment ] {
98
+ return [
99
+ . left: . left,
100
+ . right: . right,
101
+ . justified: . justified
102
+ ]
103
+ }
104
+
105
+ let layoutDirection = UIApplication . shared. userInterfaceLayoutDirection
106
+
107
+ switch layoutDirection {
108
+ case . leftToRight:
109
+ switch horizontalAlignment {
110
+ case . leading:
111
+ return . left
112
+ case . trailing:
113
+ return . right
114
+ default :
115
+ break
116
+ }
117
+
118
+ case . rightToLeft:
119
+ switch horizontalAlignment {
120
+ case . leading:
121
+ return . right
122
+ case . trailing:
123
+ return . left
124
+ default :
125
+ break
126
+ }
127
+ }
128
+
129
+ // It's safe to force-unwrap as `.leading` and `.trailing` are covered
130
+ // above and the `trivialMapping` dictionary contains all other keys.
131
+ return trivialMapping [ horizontalAlignment] !
132
+ }
77
133
78
134
/// The vertical axis with respect to which the cells are horizontally aligned.
79
135
/// For a `justified` alignment the alignment axis is not defined and this value is `nil`.
80
136
fileprivate var alignmentAxis : AlignmentAxis < HorizontalAlignment > ? {
81
- switch horizontalAlignment {
137
+ switch effectiveHorizontalAlignment {
82
138
case . left:
83
139
return AlignmentAxis ( alignment: HorizontalAlignment . left, position: sectionInset. left)
84
140
case . right:
@@ -280,6 +336,7 @@ open class AlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
280
336
}
281
337
282
338
339
+
283
340
// MARK: - 👷 Layout attributes helpers
284
341
285
342
fileprivate extension UICollectionViewLayoutAttributes {
@@ -400,7 +457,7 @@ fileprivate extension UICollectionViewLayoutAttributes {
400
457
return
401
458
}
402
459
403
- switch collectionViewLayout. horizontalAlignment {
460
+ switch collectionViewLayout. effectiveHorizontalAlignment {
404
461
405
462
case . left:
406
463
if isRepresentingFirstItemInLine ( collectionViewLayout: collectionViewLayout) {
0 commit comments