Last active
November 4, 2024 19:17
-
-
Save orgmir/a140b15c1f2ab86b2a72d4c09570cd52 to your computer and use it in GitHub Desktop.
UIView extension with AutoLayout helpers to simplify your code layout creation
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
// | |
// UIView+AutoLayout.swift | |
// | |
// Created by Luis Ramos on 21/6/17. | |
// Copyright © 2017 All rights reserved. | |
// | |
import UIKit | |
extension UIView { | |
var left: CGFloat { | |
get { return frame.origin.x } | |
set { frame = CGRect(x: newValue, y: frame.origin.y, width: frame.size.width, height: frame.size.height) } | |
} | |
var top: CGFloat { | |
get { return frame.origin.y } | |
set { frame = CGRect(x: frame.origin.x, y: newValue, width: frame.size.width, height: frame.size.height) } | |
} | |
var width: CGFloat { | |
get { return frame.size.width } | |
set { frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: newValue, height: frame.size.height) } | |
} | |
var height: CGFloat { | |
get { return frame.size.height } | |
set { frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: frame.size.width, height: newValue) } | |
} | |
var right: CGFloat { | |
get { return left + width } | |
set { left = newValue - width } | |
} | |
var bottom: CGFloat { | |
get { return top + height } | |
set { top = newValue - height } | |
} | |
var centerX: CGFloat { | |
get { return left + width * 0.5 } | |
set { left = newValue - width * 0.5 } | |
} | |
var centerY: CGFloat { | |
get { return top + height * 0.5 } | |
set { top = newValue - height * 0.5 } | |
} | |
var relativeCenter : CGPoint { | |
return CGPoint(x: bounds.width / 2.0, y: bounds.height / 2.0) | |
} | |
var size: CGSize { | |
get { return frame.size } | |
set { frame.size = newValue } | |
} | |
} | |
extension UIView { | |
@discardableResult | |
func align(with view: UIView, constant: CGFloat = 0.0) -> [NSLayoutConstraint] { | |
translatesAutoresizingMaskIntoConstraints = false | |
let constraints = [ | |
leftAnchor.constraint(equalTo: view.leftAnchor, constant: constant), | |
rightAnchor.constraint(equalTo: view.rightAnchor, constant: -constant), | |
topAnchor.constraint(equalTo: view.topAnchor, constant: constant), | |
bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -constant), | |
] | |
NSLayoutConstraint.activate(constraints) | |
return constraints | |
} | |
@discardableResult | |
func alignLeadingTrailing(with view: UIView, constant: CGFloat = 0.0) -> NSLayoutConstraint { | |
translatesAutoresizingMaskIntoConstraints = false | |
let constraints = [ | |
leftAnchor.constraint(equalTo: view.leftAnchor, constant: constant), | |
rightAnchor.constraint(equalTo: view.rightAnchor, constant: -constant), | |
] | |
NSLayoutConstraint.activate(constraints) | |
return constraints | |
} | |
@discardableResult | |
func alignTopBottom(with view: UIView, constant: CGFloat = 0.0) -> NSLayoutConstraint { | |
translatesAutoresizingMaskIntoConstraints = false | |
let constraints = [ | |
topAnchor.constraint(equalTo: view.topAnchor, constant: constant), | |
bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -constant), | |
] | |
NSLayoutConstraint.activate(constraints) | |
return constraints | |
} | |
@discardableResult | |
func alignTopBottom(with layoutGuide: UILayoutGuide, constant: CGFloat = 0.0) -> NSLayoutConstraint { | |
translatesAutoresizingMaskIntoConstraints = false | |
let constraints = [ | |
topAnchor.constraint(equalTo: layoutGuide.topAnchor, constant: constant), | |
bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor, constant: -constant), | |
] | |
NSLayoutConstraint.activate(constraints) | |
return constraints | |
} | |
@discardableResult | |
func alignTop(to anchor: NSLayoutYAxisAnchor, constant: CGFloat = 0.0, | |
priority: UILayoutPriority = .required, isActive: Bool = true) -> NSLayoutConstraint { | |
translatesAutoresizingMaskIntoConstraints = false | |
let constraint = topAnchor.constraint(equalTo: anchor, constant: constant) | |
constraint.priority = priority | |
constraint.isActive = isActive | |
return constraint | |
} | |
@discardableResult | |
func alignTop(with guide: UILayoutGuide, constant: CGFloat = 0.0, | |
priority: UILayoutPriority = .required, isActive: Bool = true) -> NSLayoutConstraint { | |
return alignTop(to: guide.topAnchor, constant: constant, priority: priority, isActive: isActive) | |
} | |
@discardableResult | |
func alignTop(with view: UIView, constant: CGFloat = 0.0, | |
priority: UILayoutPriority = .required, isActive: Bool = true) -> NSLayoutConstraint { | |
return alignTop(to: view.topAnchor, constant: constant, priority: priority, isActive: isActive) | |
} | |
@discardableResult | |
func alignBottom(to anchor: NSLayoutYAxisAnchor, constant: CGFloat = 0.0, | |
priority: UILayoutPriority = .required, isActive: Bool = true) -> NSLayoutConstraint { | |
translatesAutoresizingMaskIntoConstraints = false | |
let constraint = bottomAnchor.constraint(equalTo: anchor, constant: constant) | |
constraint.priority = priority | |
constraint.isActive = isActive | |
return constraint | |
} | |
@discardableResult | |
func alignBottom(with guide: UILayoutGuide, constant: CGFloat = 0.0, | |
priority: UILayoutPriority = .required, isActive: Bool = true) -> NSLayoutConstraint { | |
return alignBottom(to: guide.bottomAnchor, constant: constant, priority: priority, isActive: isActive) | |
} | |
@discardableResult | |
func alignBottom(with view: UIView, constant: CGFloat = 0.0, | |
priority: UILayoutPriority = .required, isActive: Bool = true) -> NSLayoutConstraint { | |
return alignBottom(to: view.bottomAnchor, constant: constant, priority: priority, isActive: isActive) | |
} | |
@discardableResult | |
func alignLeading(to anchor: NSLayoutXAxisAnchor, constant: CGFloat = 0.0, | |
priority: UILayoutPriority = .required, isActive: Bool = true) -> NSLayoutConstraint { | |
translatesAutoresizingMaskIntoConstraints = false | |
let constraint = leadingAnchor.constraint(equalTo: anchor, constant: constant) | |
constraint.isActive = isActive | |
constraint.priority = priority | |
return constraint | |
} | |
@discardableResult | |
func alignLeading(with view: UIView, constant: CGFloat = 0.0, | |
priority: UILayoutPriority = .required, isActive: Bool = true) -> NSLayoutConstraint { | |
return alignLeading(to: view.leadingAnchor, constant: constant, priority: priority, isActive: isActive) | |
} | |
@discardableResult | |
func alignTrailing(to anchor: NSLayoutXAxisAnchor, constant: CGFloat = 0.0, | |
priority: UILayoutPriority = .required, isActive: Bool = true) -> NSLayoutConstraint { | |
translatesAutoresizingMaskIntoConstraints = false | |
let constraint = trailingAnchor.constraint(equalTo: anchor, constant: constant) | |
constraint.isActive = isActive | |
constraint.priority = priority | |
return constraint | |
} | |
@discardableResult | |
func alignTrailing(with view: UIView, constant: CGFloat = 0.0, | |
priority: UILayoutPriority = .required, isActive: Bool = true) -> NSLayoutConstraint { | |
return alignTrailing(to: view.trailingAnchor, constant: constant, priority: priority, isActive: isActive) | |
} | |
@discardableResult | |
func alignBottom(toTopOf view: UIView, constant: CGFloat = 0.0, | |
priority: UILayoutPriority = .required, isActive: Bool = true) -> NSLayoutConstraint { | |
return alignBottom(to: view.topAnchor, constant: constant, priority: priority, isActive: isActive) | |
} | |
@discardableResult | |
func alignTrailing(toLeadingOf view: UIView, constant: CGFloat = 0.0, | |
priority: UILayoutPriority = .required, isActive: Bool = true) -> NSLayoutConstraint { | |
return alignTrailing(to: view.leadingAnchor, constant: constant, priority: priority, isActive: isActive) | |
} | |
@discardableResult | |
func centerVertical(with view: UIView, constant: CGFloat = 0.0, | |
priority: UILayoutPriority = .required, isActive: Bool = true) -> NSLayoutConstraint { | |
translatesAutoresizingMaskIntoConstraints = false | |
let constraint = centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: constant) | |
constraint.isActive = isActive | |
constraint.priority = priority | |
return constraint | |
} | |
@discardableResult | |
func centerHorizontal(with view: UIView, constant: CGFloat = 0.0, | |
priority: UILayoutPriority = .required, isActive: Bool = true) -> NSLayoutConstraint { | |
translatesAutoresizingMaskIntoConstraints = false | |
let constraint = centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: constant) | |
constraint.isActive = isActive | |
constraint.priority = priority | |
return constraint | |
} | |
@discardableResult | |
func constrainHeight(_ value: CGFloat, priority: UILayoutPriority = .required, | |
isActive: Bool = true) -> NSLayoutConstraint { | |
let constraint = heightAnchor.constraint(equalToConstant: value) | |
constraint.isActive = isActive | |
constraint.priority = priority | |
return constraint | |
} | |
@discardableResult | |
func constrainWidth(_ value: CGFloat, priority: UILayoutPriority = .required, | |
isActive: Bool = true) -> NSLayoutConstraint { | |
let constraint = widthAnchor.constraint(equalToConstant: value) | |
constraint.isActive = isActive | |
constraint.priority = priority | |
return constraint | |
} | |
@discardableResult | |
func constrainWidth(to view: UIView, priority: UILayoutPriority = .required, | |
isActive: Bool = true) -> NSLayoutConstraint { | |
let constraint = widthAnchor.constraint(equalTo: view.widthAnchor) | |
constraint.isActive = isActive | |
constraint.priority = priority | |
return constraint | |
} | |
@discardableResult | |
func constrainHeight(to view: UIView, priority: UILayoutPriority = .required, | |
isActive: Bool = true) -> NSLayoutConstraint { | |
let constraint = heightAnchor.constraint(equalTo: view.heightAnchor) | |
constraint.isActive = isActive | |
constraint.priority = priority | |
return constraint | |
} | |
func constraintSize(width: CGFloat, height: CGFloat, | |
priority: UILayoutPriority = .required, isActive: Bool = true) { | |
constrainWidth(width, priority: priority, isActive: isActive) | |
constrainHeight(height, priority: priority, isActive: isActive) | |
} | |
@discardableResult | |
func constrainHeightToWidth(ratio: CGFloat = 1, priority: UILayoutPriority = .required, | |
isActive: Bool = true) -> NSLayoutConstraint { | |
let constraint = heightAnchor.constraint(equalTo: widthAnchor, multiplier: ratio) | |
constraint.isActive = isActive | |
constraint.priority = priority | |
return constraint | |
} | |
@discardableResult | |
func constrainWidthToHeight(ratio: CGFloat = 1, priority: UILayoutPriority = .required, | |
isActive: Bool = true) -> NSLayoutConstraint { | |
let constraint = widthAnchor.constraint(equalTo: heightAnchor, multiplier: ratio) | |
constraint.isActive = isActive | |
constraint.priority = priority | |
return constraint | |
} | |
} | |
extension UIView { | |
var layoutGuide: UILayoutGuide { | |
if #available(iOS 11.0, *) { | |
return safeAreaLayoutGuide | |
} else { | |
return layoutMarginsGuide | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment