Skip to content

Instantly share code, notes, and snippets.

@ostholz
Created October 15, 2021 18:41
Show Gist options
  • Save ostholz/344412af8bd28c32260671e318217f1b to your computer and use it in GitHub Desktop.
Save ostholz/344412af8bd28c32260671e318217f1b to your computer and use it in GitHub Desktop.
Handy AutoLayout Extension
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