Swift CGRect
Extension that make manipulating and laying out frames a bunch easier. For people who are frustrated by AutoLayout but also tired of doing rote calculations to create simple layouts.
Why would you want to manipulate CGRects
? Well often the point of configuring CGRects
is so you can use them to position UIViews
. Many people try to do this using AutoLayout in either Interface Builder or programmatcially, and if you've found that an easy solution, blessings upon you. For anyone tired of struggling with that, here's a simple way to do a few simple things.
Of course, the manipulations provided here don't directly affect any UIViews
from which the frames may have been derived, so once you've pulled the frames out and fiddled with them, you'll have to re-apply them to the UIVIews
manually.
note: To keep this repository simple I've just had it cover CGRect
. I do have an extension of UIView
that adds all this functionality to UIViews
, but it's not stand-alone, it's part of my NautoLayout repository, which also includes a slew of other helpful stuff if you want to avoid AutoLayout.
rect.x
and rect.y
are accessible directly. What could be easier?
To copy a CGRect
and only change the height, it's as simple as
let rectCopy = rect.copyWithNew(height: 200)
Same can be done for x, y, and width, as well as any combination of them, as in:
let rectCopy = rect.copyWithNew(y: 15, width: 200)
Like this:
let newRect = rect.copyAtZeroZero()
A collection of functions that lets any CGRect take a set of other CGRects and set all their x and y values to lay them out in simple ways.
layoutVerticallyAlongCenterX(subRects rects: [CGRect], margin: CGFloat? = nil)-> [CGRect]
layoutVertically(subRects rects: [CGRect], centerX: CGFloat, margin: CGFloat? = nil)->[CGRect]
layoutVertically(subRects rects: [CGRect], proportionalCenterX: CGFloat, margin: CGFloat? = nil)->[CGRect]
layoutHorizontallyAlongCenterY(subRects rects: [CGRect], margin: CGFloat? = nil)-> [CGRect]
layoutHorizontally(subRects rects: [CGRect], centerY: CGFloat, margin: CGFloat? = nil)->[CGRect]
layoutHorizontally(subRects rects: [CGRect], proportionalCenterY: CGFloat, margin: CGFloat? = nil)->[CGRect]
layoutVerticallyAlongCenterX
will allow a CGRrect
to take in a bunch of other CGRects
and return them evenly spaced right down its center:
let mainRect = CGRect( ...whatever dimensions desired...)
let setOfRects = [rectA, rectB, rectC]
let verticalSet = mainRect.layoutVerticallyAlongCenterX(rects: setOfRects)
If you want to specify a different center X to align them along, you can just use layoutVertically
.
let mainRect = CGRect( ...whatever dimensions desired...)
let setOfRects = [rectA, rectB, rectC]
let arbitrarySet = mainRect.layoutVertically(rects: setOfRects, centerX: 20)
And if you want to use a proportional X value instead of a literal one, you can do that with an overloaded version of layoutVertically
. This example lays out the sub-rects vertically centered on the left side of the parent:
let mainRect = CGRect( ...whatever dimensions desired...)
let setOfRects = [rectA, rectB, rectC]
let proportionalSet = mainRect.layoutVertically(rects: setOfRects, proportionalCenterX: 0.25)
And of course, the exact same functionality is provided for horizontal layouts.
...
//centered along horizontal median:
let horizontalRects = layoutHorizontallyAlongCenterY(rects: setOfRects)
...
//centered along arbitrary horizontal position:
let arbitrarySet = layoutHorizontally(rects: setOfRects centerY: 22)
...
//centered along horizontal position expressed as a proportion of the parent's height
//in this case close to the left side of the parent:
let proportionalSet = layoutHorizontally(rects: setOfRects centerY: 0.75)
Every one of the layout commands has an optional margin
parameter that lets you specify a padding amount that will be added to the vertical or horizontal end boundaries, whatever the case may be. Two examples:
...
let verticalRects = mainRect.layoutVerticallyAlongCenterX(rects: setOfRects, margin: 12)
...
let proportionallyHorizontalRects = layoutHorizontally(rects: setOfRects centerY: 0.75, margin: 8)
note: ideally the proportional overloads would let the margin be expressed proportionally as well, but at present, they don't.
I'm sure there are others out there who prefer to do things by hand but would love a few handy shortcuts. I hope these help!