Created
October 15, 2021 18:41
-
-
Save ostholz/344412af8bd28c32260671e318217f1b to your computer and use it in GitHub Desktop.
Handy AutoLayout Extension
This file contains 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
extension UIView { | |
/** | |
* Set aspect ratio for self | |
* | |
* Examples: there is a view `v` | |
* v.aspectRatio(ratio: 2.0) | |
*/ | |
public func aspectRatio(ratio: CGFloat) { | |
self.translatesAutoresizingMaskIntoConstraints = false | |
self.widthAnchor.constraint(equalTo: self.heightAnchor, multiplier: ratio).isActive = true | |
} | |
/** | |
* align the view with other view with common ancestor. | |
* | |
* Examples: | |
* place viewA under viewB with 8pt distance | |
* viewA.align(to viewB, source: .top, target: .bottom, constant: 8) | |
*/ | |
public func align(to sibling: UIView, source: NSLayoutConstraint.Attribute, target: NSLayoutConstraint.Attribute, constant: CGFloat = 0) { | |
guard let _ = self.superview else { return } | |
guard let _ = sibling.superview else { return } | |
self.translatesAutoresizingMaskIntoConstraints = false | |
sibling.translatesAutoresizingMaskIntoConstraints = false | |
NSLayoutConstraint(item: self, attribute: source, relatedBy: .equal, toItem: sibling, attribute: target, multiplier: 1.0, constant: constant).isActive = true | |
} | |
/** | |
* align the view in a superView with Left and Right. the four Anchors are optional, but at least one Anchor shoud present. | |
* | |
* Examples 1: | |
* place viewA into container with horizontal anchors. Note: right and bottom hier are with positiv values | |
* viewA.align(in container, left: 8, top: nil, right: 8, bottom: nil) | |
*/ | |
public func align(in parent: UIView, left: CGFloat?, top: CGFloat?, right: CGFloat?, bottom: CGFloat?) { | |
parent.addSubview(self) | |
self.translatesAutoresizingMaskIntoConstraints = false | |
parent.translatesAutoresizingMaskIntoConstraints = false | |
var constraints = [NSLayoutConstraint]() | |
if let left = left { | |
let constraint = self.leftAnchor.constraint(equalTo: parent.leftAnchor, constant: left) | |
constraints.append(constraint) | |
} | |
if let top = top { | |
let constraint = self.topAnchor.constraint(equalTo: parent.safeAreaLayoutGuide.topAnchor, constant: top) | |
constraints.append(constraint) | |
} | |
if let right = right { | |
let constraint = self.rightAnchor.constraint(equalTo: parent.rightAnchor, constant: -right) | |
constraints.append(constraint) | |
} | |
if let bottom = bottom { | |
let constraint = self.bottomAnchor.constraint(equalTo: parent.bottomAnchor, constant: -bottom) | |
constraints.append(constraint) | |
} | |
NSLayoutConstraint.activate(constraints) | |
} | |
/** | |
* align the view in a superView with Leading and Trailing. the four Anchors are optional, but at least one Anchor shoud present. | |
* | |
* Examples 1: | |
* place viewA into container with horizontal anchors. Note: right and bottom hier are with positiv values | |
* viewA.align(in container, leading: 8, top: 16, right: 8, bottom: nil) | |
*/ | |
public func align(in parent: UIView, leading: CGFloat?, top: CGFloat?, trailing: CGFloat?, bottom: CGFloat?) { | |
parent.addSubview(self) | |
self.translatesAutoresizingMaskIntoConstraints = false | |
parent.translatesAutoresizingMaskIntoConstraints = false | |
var constraints = [NSLayoutConstraint]() | |
if let leading = leading { | |
if parent is UIScrollView { | |
constraints.append(self.leadingAnchor.constraint(equalTo: parent.leadingAnchor, constant: leading)) | |
} else { | |
constraints.append(self.leadingAnchor.constraint(equalTo: parent.safeAreaLayoutGuide.leadingAnchor, constant: leading)) | |
} | |
} | |
if let top = top { | |
if parent is UIScrollView{ | |
constraints.append(self.topAnchor.constraint(equalTo: parent.topAnchor, constant: top)) | |
} else { | |
constraints.append(self.topAnchor.constraint(equalTo: parent.safeAreaLayoutGuide.topAnchor, constant: top)) | |
} | |
} | |
if let trailing = trailing { | |
if parent is UIScrollView { | |
constraints.append(self.trailingAnchor.constraint(equalTo: parent.trailingAnchor, constant: -trailing)) | |
} else { | |
constraints.append(self.trailingAnchor.constraint(equalTo: parent.safeAreaLayoutGuide.trailingAnchor, constant: -trailing)) | |
} | |
} | |
if let bottom = bottom { | |
if parent is UIScrollView { | |
constraints.append(self.bottomAnchor.constraint(equalTo: parent.bottomAnchor, constant: bottom)) | |
} else { | |
constraints.append(self.bottomAnchor.constraint(equalTo: parent.safeAreaLayoutGuide.bottomAnchor, constant: bottom)) | |
} | |
} | |
NSLayoutConstraint.activate(constraints) | |
} | |
/** | |
* align the views'center with other view's center in x- and y-Axis. | |
* | |
* Examples: | |
* viewA.align(with viewB, xAxis: true, xOffset: 0, yAxis: true, yOffset: 0) | |
*/ | |
public func alignCenter(with target: UIView, xAxis: Bool, xOffset: CGFloat = 0, yAxis: Bool, yOffset: CGFloat = 0) { | |
var constraints = [NSLayoutConstraint]() | |
if xAxis { | |
constraints.append(self.centerXAnchor.constraint(equalTo: target.centerXAnchor, constant: xOffset)) | |
} | |
if yAxis { | |
constraints.append(self.centerYAnchor.constraint(equalTo: target.centerYAnchor, constant: yOffset)) | |
} | |
NSLayoutConstraint.activate(constraints) | |
} | |
/** | |
* set the views's height with other in proportion | |
* | |
* Examples: | |
* viewA.alignHeight(with viewB, percent: 0.5) | |
*/ | |
public func alignHeight(with target: UIView, percent: CGFloat = 1.0) { | |
self.translatesAutoresizingMaskIntoConstraints = false | |
target.translatesAutoresizingMaskIntoConstraints = false | |
self.heightAnchor.constraint(equalTo: target.heightAnchor, multiplier: percent).isActive = true | |
} | |
/** | |
* set the views's width with other in proportion | |
* | |
* Examples: | |
* viewA.alignWidth(with viewB, percent: 0.5) | |
*/ | |
public func alignWidth(with target: UIView, percent: CGFloat = 1.0) { | |
self.translatesAutoresizingMaskIntoConstraints = false | |
target.translatesAutoresizingMaskIntoConstraints = false | |
self.widthAnchor.constraint(equalTo: target.widthAnchor, multiplier: percent).isActive = true | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment