Last active
December 8, 2017 16:37
-
-
Save JARinteractive/96cbba8f35dcd10bbb77 to your computer and use it in GitHub Desktop.
Simplify frame-based layout
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://gist.github.com/JARinteractive/96cbba8f35dcd10bbb77 | |
import UIKit | |
extension CGSize { | |
public func centered(in rect: CGRect) -> CGRect { | |
let centeredPoint = CGPoint(x: rect.minX + abs(rect.width - width) / 2, y: rect.minY + abs(rect.height - height) / 2) | |
let size = CGSize(width: min(self.width, rect.width), height: min(self.height, rect.height)) | |
let point = CGPoint(x: max(centeredPoint.x, rect.minX), y: max(centeredPoint.y, rect.minY)) | |
return CGRect(origin: point, size: size) | |
} | |
public func centeredHorizontally(in rect: CGRect, top: CGFloat) -> CGRect { | |
var rect = centered(in: rect) | |
rect.origin.y = top | |
return rect | |
} | |
public func centeredVertically(in rect: CGRect, left: CGFloat) -> CGRect { | |
var rect = centered(in: rect) | |
rect.origin.x = left | |
return rect | |
} | |
public func with(width: CGFloat) -> CGSize { | |
return CGSize(width: width, height: self.height) | |
} | |
public func with(height: CGFloat) -> CGSize { | |
return CGSize(width: self.width, height: height) | |
} | |
} | |
extension CGFloat { | |
public func roundedToPixel() -> CGFloat { | |
return Foundation.ceil(self * AlignmentStrategy.scale) / AlignmentStrategy.scale | |
} | |
public func roundedDownToPixel() -> CGFloat { | |
return Foundation.floor(self * AlignmentStrategy.scale) / AlignmentStrategy.scale | |
} | |
} | |
public struct AlignmentStrategy { | |
let xAlignment: (CGFloat) -> CGFloat | |
let yAlignment: (CGFloat) -> CGFloat | |
let widthAlignment: (CGFloat) -> CGFloat | |
let heightAlignment: (CGFloat) -> CGFloat | |
public static let scale = UIScreen.main.scale | |
init(alignment: @escaping (CGFloat) -> CGFloat) { | |
xAlignment = alignment | |
yAlignment = alignment | |
widthAlignment = alignment | |
heightAlignment = alignment | |
} | |
init(originAlignment: @escaping (CGFloat) -> CGFloat, sizeAlignment: @escaping (CGFloat) -> CGFloat) { | |
xAlignment = originAlignment | |
yAlignment = originAlignment | |
widthAlignment = sizeAlignment | |
heightAlignment = sizeAlignment | |
} | |
init(xAlignment: @escaping (CGFloat) -> CGFloat, yAlignment: @escaping (CGFloat) -> CGFloat, widthAlignment: @escaping (CGFloat) -> CGFloat, heightAlignment: @escaping (CGFloat) -> CGFloat) { | |
self.xAlignment = xAlignment | |
self.yAlignment = yAlignment | |
self.widthAlignment = widthAlignment | |
self.heightAlignment = heightAlignment | |
} | |
func align(rect: CGRect) -> CGRect { | |
return CGRect(x: xAlignment(rect.origin.x), y: yAlignment(rect.origin.y), width: widthAlignment(rect.width), height: heightAlignment(rect.height)) | |
} | |
public static var roundToPixel: AlignmentStrategy { | |
return AlignmentStrategy { | |
return round($0 * AlignmentStrategy.scale) / AlignmentStrategy.scale | |
} | |
} | |
public static var label: AlignmentStrategy { | |
return AlignmentStrategy { | |
return ceil($0 * AlignmentStrategy.scale) / AlignmentStrategy.scale | |
} | |
} | |
} | |
extension CGRect { | |
public func align(strategy: AlignmentStrategy = .roundToPixel) -> CGRect { | |
return strategy.align(rect: self) | |
} | |
public var center:CGPoint { | |
return CGPoint(x: midX, y: midY) | |
} | |
public static var nonZero: CGRect { return CGRect(x: 0, y: 0, width: 100, height: 100) } | |
public init(x: CGFloat, y: CGFloat, size: CGSize) { | |
self.init(x: x, y: y, width: size.width, height: size.height) | |
} | |
public init(origin: CGPoint, width: CGFloat, height: CGFloat) { | |
self.init(x: origin.x, y: origin.y, width: width, height: height) | |
} | |
public func with(width value: CGFloat) -> CGRect { | |
return CGRect(x: minX, y: minY, width: value, height: height) | |
} | |
public func with(height value: CGFloat) -> CGRect { | |
return CGRect(x: minX, y: minY, width: width, height: value) | |
} | |
public func with(x value: CGFloat) -> CGRect { | |
return CGRect(x: value, y: minY, width: width, height: height) | |
} | |
public func with(y value: CGFloat) -> CGRect { | |
return CGRect(x: minX, y: value, width: width, height: height) | |
} | |
public func insetBy(top: CGFloat = 0, left: CGFloat = 0, bottom: CGFloat = 0, right: CGFloat = 0) -> CGRect { | |
return UIEdgeInsetsInsetRect(self, UIEdgeInsets(top: top, left: left, bottom: bottom, right: right)) | |
} | |
} | |
public func -(point1: CGPoint, point2: CGPoint) -> CGSize { | |
return CGSize(width: point1.x - point2.x, height: point1.y - point2.y) | |
} | |
public func +(point: CGPoint, size: CGSize) -> CGPoint { | |
return CGPoint(x: point.x - size.width, y: point.y - size.height) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment