@@ -150,6 +150,109 @@ extension UIView {
150
150
}
151
151
}
152
152
153
+ #if swift(>=5.4)
154
+ /// Arranges subviews along the vertical axis according to a distribution with fixed and/or flexible spacers.
155
+ ///
156
+ /// * If there are no flexible elements, this will treat the distribution as vertically centered (i.e. with two
157
+ /// flexible elements of equal weight at the top and bottom, respectively).
158
+ /// * If there are no spacers (fixed or flexible), this will treat the distribution as equal flexible spacing
159
+ /// at the top, bottom, and between each view.
160
+ ///
161
+ /// **Examples:**
162
+ ///
163
+ /// To stack two elements with a 10 pt margin between them:
164
+ /// ```
165
+ /// // This is effectively the same as [ 1.flexible, icon, 10.fixed, label, 1.flexible ].
166
+ /// applyVerticalSubviewDistribution {
167
+ /// icon
168
+ /// 10.fixed
169
+ /// label
170
+ /// }
171
+ /// ```
172
+ ///
173
+ /// To evenly spread out items:
174
+ /// ```
175
+ /// // This is effectively the same as [ 1.flexible, button1, 1.flexible, button2, 1.flexible, button3 ].
176
+ /// applyVerticalSubviewDistribution {
177
+ /// button1
178
+ /// button2
179
+ /// button3
180
+ /// }
181
+ /// ```
182
+ ///
183
+ /// To stack two elements with 50% more space below than above:
184
+ /// ```
185
+ /// applyVerticalSubviewDistribution {
186
+ /// 2.flexible
187
+ /// label
188
+ /// 12.fixed
189
+ /// textField
190
+ /// 3.flexible
191
+ /// }
192
+ /// ```
193
+ ///
194
+ /// To arrange a pair of label on the top and bottom edges of a view, with another label centered between them:
195
+ /// ```
196
+ /// applyVerticalSubviewDistribution {
197
+ /// 8.fixed
198
+ /// headerLabel
199
+ /// 1.flexible
200
+ /// bodyLabel
201
+ /// 1.flexible
202
+ /// footerLabel
203
+ /// 8.fixed
204
+ /// }
205
+ /// ```
206
+ ///
207
+ /// To arrange UI in a view with an interior margin:
208
+ /// ```
209
+ /// applyVerticalSubviewDistribution {
210
+ /// icon
211
+ /// 10.fixed
212
+ /// label
213
+ /// }, inRect: bounds.insetBy(dx: 20, dy: 40))
214
+ /// ```
215
+ ///
216
+ /// To arrange UI vertically aligned by their leading edge 10 pt in from the leading edge of their superview:
217
+ /// ```
218
+ /// applyVerticalSubviewDistribution {
219
+ /// icon
220
+ /// 1.flexible
221
+ /// button
222
+ /// }, orthogonalOffset: .leading(inset: 10))
223
+ /// ```
224
+ ///
225
+ /// To arrange UI vertically without simultaneously centering it horizontally (the `icon` would need independent
226
+ /// horizontal positioning):
227
+ /// ```
228
+ /// applyVerticalSubviewDistribution {
229
+ /// 1.flexible
230
+ /// icon
231
+ /// 2.flexible
232
+ /// }, orthogonalOffset: nil)
233
+ /// ```
234
+ ///
235
+ /// - precondition: All views in the `distribution` must be subviews of the receiver.
236
+ /// - precondition: The `distribution` must not include any given view more than once.
237
+ ///
238
+ /// - parameter distribution: An array of distribution specifiers, ordered from the top edge to the bottom edge.
239
+ /// - parameter layoutBounds: The region in the receiver in which to distribute the view in the receiver's
240
+ /// coordinate space. Specify `nil` to use the receiver's bounds. Defaults to `nil`.
241
+ /// - parameter orthogonalAlignment: The horizontal alignment to apply to the views. If `nil`, views are left in
242
+ /// their horizontal position prior to the distribution. Defaults to centered with no offset.
243
+ public func applyVerticalSubviewDistribution(
244
+ @ViewDistributionBuilder _ distribution: ( ) -> [ ViewDistributionSpecifying ] ,
245
+ inRect layoutBounds: CGRect ? = nil ,
246
+ orthogonalAlignment: HorizontalDistributionAlignment ? = . centered( offset: 0 )
247
+ ) {
248
+ applyVerticalSubviewDistribution (
249
+ distribution ( ) ,
250
+ inRect: layoutBounds,
251
+ orthogonalAlignment: orthogonalAlignment
252
+ )
253
+ }
254
+ #endif
255
+
153
256
/// Arranges subviews along the horizontal axis according to a distribution with fixed and/or flexible spacers.
154
257
///
155
258
/// * If there are no flexible elements, this will treat the distribution as horizontally centered (i.e. with two
@@ -229,6 +332,110 @@ extension UIView {
229
332
}
230
333
}
231
334
335
+ #if swift(>=5.4)
336
+ /// Arranges subviews along the horizontal axis according to a distribution with fixed and/or flexible spacers.
337
+ ///
338
+ /// * If there are no flexible elements, this will treat the distribution as horizontally centered (i.e. with two
339
+ /// flexible elements of equal weight at the leading and trailing edges, respectively).
340
+ /// * If there are no spacers (fixed or flexible), this will treat the distribution as equal flexible spacing
341
+ /// at the leading edge, trailing edge, and between each view.
342
+ ///
343
+ /// **Examples:**
344
+ ///
345
+ /// To stack two elements with a 10 pt margin between them:
346
+ /// ```
347
+ /// // This is effectively the same as [ 1.flexible, icon, 10.fixed, label, 1.flexible ].
348
+ /// applyHorizontalSubviewDistribution {
349
+ /// icon
350
+ /// 10.fixed
351
+ /// label
352
+ /// }
353
+ /// ```
354
+ ///
355
+ /// To evenly spread out items:
356
+ /// ```
357
+ /// // This is effectively the same as [ 1.flexible, button1, 1.flexible, button2, 1.flexible, button3 ].
358
+ /// applyHorizontalSubviewDistribution {
359
+ /// button1
360
+ /// button2
361
+ /// button3
362
+ /// }
363
+ /// ```
364
+ ///
365
+ /// To stack two elements with 50% more space after than before:
366
+ /// ```
367
+ /// applyHorizontalSubviewDistribution {
368
+ /// 2.flexible
369
+ /// label
370
+ /// 12.fixed
371
+ /// textField
372
+ /// 3.flexible
373
+ /// }
374
+ /// ```
375
+ ///
376
+ /// To arrange a pair of buttons on the left and right edges of a view, with a label centered between them:
377
+ /// ```
378
+ /// applyHorizontalSubviewDistribution {
379
+ /// 8.fixed
380
+ /// backButton
381
+ /// 1.flexible
382
+ /// titleLabel
383
+ /// 1.flexible
384
+ /// nextButton
385
+ /// 8.fixed
386
+ /// }
387
+ /// ```
388
+ ///
389
+ /// To arrange UI in a view with an interior margin:
390
+ /// ```
391
+ /// applyHorizontalSubviewDistribution {
392
+ /// icon
393
+ /// 10.fixed
394
+ /// label
395
+ /// }, inRect: bounds.insetBy(dx: 20, dy: 40))
396
+ /// ```
397
+ ///
398
+ /// To arrange UI horizontally aligned by their top edge 10 pt in from the top edge of their superview:
399
+ /// ```
400
+ /// applyHorizontalSubviewDistribution {
401
+ /// icon
402
+ /// 1.flexible
403
+ /// button
404
+ /// }, orthogonalOffset: .top(inset: 10))
405
+ /// ```
406
+ ///
407
+ /// To arrange UI horizontally without simultaneously centering it vertically (the `icon` would need independent
408
+ /// vertical positioning):
409
+ /// ```
410
+ /// applyHorizontalSubviewDistribution {
411
+ /// 1.flexible
412
+ /// icon
413
+ /// 2.flexible
414
+ /// }, orthogonalOffset: nil)
415
+ /// ```
416
+ ///
417
+ /// - precondition: All views in the `distribution` must be subviews of the receiver.
418
+ /// - precondition: The `distribution` must not include any given view more than once.
419
+ ///
420
+ /// - parameter distribution: An array of distribution specifiers, ordered from the leading edge to the trailing
421
+ /// edge.
422
+ /// - parameter layoutBounds: The region in the receiver in which to distribute the view in the receiver's
423
+ /// coordinate space. Specify `nil` to use the receiver's bounds. Defaults to `nil`.
424
+ /// - parameter orthogonalAlignment: The vertical alignment to apply to the views. If `nil`, views are left in
425
+ /// their vertical position prior to the distribution. Defaults to centered with no offset.
426
+ public func applyHorizontalSubviewDistribution(
427
+ @ViewDistributionBuilder _ distribution: ( ) -> [ ViewDistributionSpecifying ] ,
428
+ inRect layoutBounds: CGRect ? = nil ,
429
+ orthogonalAlignment: VerticalDistributionAlignment ? = . centered( offset: 0 )
430
+ ) {
431
+ applyHorizontalSubviewDistribution (
432
+ distribution ( ) ,
433
+ inRect: layoutBounds,
434
+ orthogonalAlignment: orthogonalAlignment
435
+ )
436
+ }
437
+ #endif
438
+
232
439
// MARK: - Private Methods
233
440
234
441
private func applySubviewDistribution(
0 commit comments