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
- /**
36
- Defines an alignment for UI elements.
37
-
38
- - Note:
39
- To support semantics for Right-to-Left language Users, use `leading` or `trailing`
40
- just like you do with Autolayout.
41
-
42
- If you want to force frame based `left` or `right` alighment, use `left` or `right`
43
- */
36
+ /// Defines a horizontal alignment for UI elements.
44
37
public enum HorizontalAlignment : Alignment {
45
38
case left
46
- case justified
47
39
case right
48
40
case leading
49
41
case trailing
50
-
51
- /// trailing becomes right, and leading becomes left for RTL languages
52
- var swapForRTL : HorizontalAlignment {
53
- switch self {
54
- case . leading:
55
- return isRTL ? . right : . left
56
- case . trailing:
57
- return isRTL ? . left : . right
58
- default :
59
- return self
60
- }
61
- }
42
+ case justified
62
43
}
63
44
64
45
/// Defines a vertical alignment for UI elements.
@@ -68,6 +49,14 @@ public enum VerticalAlignment: Alignment {
68
49
case bottom
69
50
}
70
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
+
71
60
/// Describes an axis with respect to which items can be aligned.
72
61
private struct AlignmentAxis < A: Alignment > {
73
62
@@ -81,6 +70,9 @@ private struct AlignmentAxis<A: Alignment> {
81
70
}
82
71
83
72
73
+
74
+ // MARK: - Flow Layout
75
+
84
76
/// A `UICollectionViewFlowLayout` subclass that gives you control
85
77
/// over the horizontal and vertical alignment of the cells.
86
78
/// You can use it to align the cells like words in a left- or right-aligned text
@@ -92,15 +84,57 @@ open class AlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
92
84
/// Determines how the cells are horizontally aligned in a row.
93
85
/// - Note: The default is `.justified`.
94
86
public var horizontalAlignment : HorizontalAlignment = . justified
95
-
87
+
96
88
/// Determines how the cells are vertically aligned in a row.
97
89
/// - Note: The default is `.center`.
98
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
+ }
99
133
100
134
/// The vertical axis with respect to which the cells are horizontally aligned.
101
135
/// For a `justified` alignment the alignment axis is not defined and this value is `nil`.
102
136
fileprivate var alignmentAxis : AlignmentAxis < HorizontalAlignment > ? {
103
- switch horizontalAlignment . swapForRTL {
137
+ switch effectiveHorizontalAlignment {
104
138
case . left:
105
139
return AlignmentAxis ( alignment: HorizontalAlignment . left, position: sectionInset. left)
106
140
case . right:
@@ -302,6 +336,7 @@ open class AlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
302
336
}
303
337
304
338
339
+
305
340
// MARK: - 👷 Layout attributes helpers
306
341
307
342
fileprivate extension UICollectionViewLayoutAttributes {
@@ -422,7 +457,7 @@ fileprivate extension UICollectionViewLayoutAttributes {
422
457
return
423
458
}
424
459
425
- switch collectionViewLayout. horizontalAlignment . swapForRTL {
460
+ switch collectionViewLayout. effectiveHorizontalAlignment {
426
461
427
462
case . left:
428
463
if isRepresentingFirstItemInLine ( collectionViewLayout: collectionViewLayout) {
@@ -452,7 +487,3 @@ fileprivate extension UICollectionViewLayoutAttributes {
452
487
}
453
488
454
489
}
455
-
456
- fileprivate var isRTL : Bool {
457
- return UIApplication . shared. userInterfaceLayoutDirection == . rightToLeft
458
- }
0 commit comments