Created
October 1, 2020 00:04
-
-
Save imthath-m/9f3ab4e4207e480a991fac65c54f70ad to your computer and use it in GitHub Desktop.
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
import UIKit | |
public extension UIView { | |
@discardableResult func align(_ type1: NSLayoutConstraint.Attribute, | |
with view: UIView? = nil, on type2: NSLayoutConstraint.Attribute? = nil, | |
offset constant: CGFloat = 0, | |
priority: Float? = nil) -> NSLayoutConstraint? { | |
guard let view = view ?? superview else { | |
return nil | |
} | |
translatesAutoresizingMaskIntoConstraints = false | |
let type2 = type2 ?? type1 | |
let constraint = NSLayoutConstraint(item: self, attribute: type1, | |
relatedBy: .equal, | |
toItem: view, attribute: type2, | |
multiplier: 1, constant: constant) | |
if let priority = priority { | |
constraint.priority = UILayoutPriority.init(priority) | |
} | |
constraint.isActive = true | |
return constraint | |
} | |
func alignEdges(with view: UIView? = nil, offset constant: CGFloat = 0) { | |
align(.top, with: view, offset: constant) | |
align(.bottom, with: view, offset: -constant) | |
align(.leading, with: view, offset: constant) | |
align(.trailing, with: view, offset: -constant) | |
} | |
func align(greaterThanHeight height: CGFloat) { | |
translatesAutoresizingMaskIntoConstraints = false | |
addConstraint(NSLayoutConstraint(item: self, attribute: .height, relatedBy: .greaterThanOrEqual, | |
toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: height)) | |
} | |
func alignHorizontally(with view: UIView? = nil, offset constant: CGFloat = 0) { | |
align(.leading, with: view, offset: constant) | |
align(.trailing, with: view, offset: -constant) | |
} | |
func alignVertically(with view: UIView? = nil, offset constant: CGFloat = 0) { | |
align(.top, with: view, offset: constant) | |
align(.bottom, with: view, offset: -constant) | |
} | |
func alignTop(with view: UIView? = nil, offset constant: CGFloat = 0) { | |
align(.top, with: view, offset: constant) | |
align(.leading, with: view, offset: constant) | |
align(.trailing, with: view, offset: -constant) | |
} | |
func alignBottom(with view: UIView? = nil, offset constant: CGFloat = 0) { | |
align(.bottom, with: view, offset: -constant) | |
align(.leading, with: view, offset: constant) | |
align(.trailing, with: view, offset: -constant) | |
} | |
func alignCenter(with view: UIView? = nil, offset constant: CGFloat = 0) { | |
align(.centerX, with: view) | |
align(.centerY, with: view) | |
} | |
func alignLeading(with view: UIView? = nil, offset constant: CGFloat = 0) { | |
align(.top, with: view, offset: constant) | |
align(.bottom, with: view, offset: -constant) | |
align(.leading, with: view, offset: constant) | |
} | |
func alignTrailing(with view: UIView? = nil, offset constant: CGFloat = 0) { | |
align(.top, with: view, offset: constant) | |
align(.bottom, with: view, offset: -constant) | |
align(.trailing, with: view, offset: -constant) | |
} | |
func align(_ attributes: [NSLayoutConstraint.Attribute], with view: UIView? = nil, offset constant: CGFloat = 0) { | |
for attribute in attributes { | |
align(attribute, with: view, offset: constant) | |
} | |
} | |
} | |
// fixing sizes | |
public extension UIView { | |
enum SizeAttribute { | |
case height | |
case width | |
} | |
func fixSize(_ size: CGSize) { | |
fixWidth(size.width) | |
fixHeight(size.height) | |
} | |
func fixWidth(_ width: CGFloat) { | |
translatesAutoresizingMaskIntoConstraints = false | |
self.widthAnchor.constraint(equalToConstant: width).isActive = true | |
} | |
func fixHeight(_ height: CGFloat) { | |
translatesAutoresizingMaskIntoConstraints = false | |
self.heightAnchor.constraint(equalToConstant: height).isActive = true | |
} | |
func minWidth(_ width: CGFloat) { | |
translatesAutoresizingMaskIntoConstraints = false | |
self.widthAnchor.constraint(greaterThanOrEqualToConstant: width).isActive = true | |
} | |
func maxWidth(_ width: CGFloat) { | |
translatesAutoresizingMaskIntoConstraints = false | |
self.widthAnchor.constraint(lessThanOrEqualToConstant: width).isActive = true | |
} | |
func minHeight(_ width: CGFloat) { | |
translatesAutoresizingMaskIntoConstraints = false | |
self.heightAnchor.constraint(greaterThanOrEqualToConstant: width).isActive = true | |
} | |
func maxHeight(_ width: CGFloat) { | |
translatesAutoresizingMaskIntoConstraints = false | |
self.heightAnchor.constraint(lessThanOrEqualToConstant: width).isActive = true | |
} | |
func setContentSize(along axis: NSLayoutConstraint.Axis) { | |
setContentHuggingPriority(.defaultHigh, for: axis) | |
setContentCompressionResistancePriority(.defaultHigh, for: axis) | |
} | |
func make(_ sizeAttribute: SizeAttribute, fraction multiplier: CGFloat = 1, as view: UIView, offset: CGFloat = 0) { | |
self.getAnchor(for: sizeAttribute).constraint(equalTo: view.getAnchor(for: sizeAttribute), | |
multiplier: multiplier, constant: offset).isActive = true | |
} | |
private func getAnchor(for sizeAttribute: SizeAttribute) -> NSLayoutDimension { | |
switch sizeAttribute { | |
case .height: | |
return self.heightAnchor | |
case .width: | |
return self.widthAnchor | |
} | |
} | |
/// updates the semantic content attribute direction for this view based on the SDK language | |
func updateLayoutDirection() { | |
if UIView.isForcedRTL { | |
semanticContentAttribute = .forceRightToLeft | |
} else { | |
semanticContentAttribute = .forceLeftToRight | |
} | |
} | |
} | |
// alignment for notched displays, iOS 11+ | |
public extension UIView { | |
// enum SideAttribute { | |
// case leading | |
// case trailing | |
// case top | |
// case bottom | |
// } | |
func alignSafe(with view: UIView) { | |
let guide = view.getLayoutGuide() | |
self.translatesAutoresizingMaskIntoConstraints = false | |
self.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true | |
self.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true | |
self.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true | |
self.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true | |
} | |
func alignTopSafe(with view: UIView) { | |
let guide = view.getLayoutGuide() | |
self.translatesAutoresizingMaskIntoConstraints = false | |
self.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true | |
self.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true | |
self.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true | |
} | |
func alignBottomSafe(with view: UIView) { | |
let guide = view.getLayoutGuide() | |
self.translatesAutoresizingMaskIntoConstraints = false | |
self.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true | |
self.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true | |
self.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true | |
} | |
func alignLeadingSafe(with view: UIView) { | |
let guide = view.getLayoutGuide() | |
self.translatesAutoresizingMaskIntoConstraints = false | |
self.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true | |
self.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true | |
self.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true | |
} | |
func alignTrailingSafe(with view: UIView) { | |
let guide = view.getLayoutGuide() | |
self.translatesAutoresizingMaskIntoConstraints = false | |
self.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true | |
self.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true | |
self.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true | |
} | |
func getLayoutGuide() -> UILayoutGuide { | |
if #available(iOS 11.0, *) { | |
return self.safeAreaLayoutGuide | |
} | |
return self.layoutMarginsGuide | |
} | |
var safeRect: CGRect { getLayoutGuide().layoutFrame } | |
var safeHeight: CGFloat { getLayoutGuide().layoutFrame.height } | |
var safeWidth: CGFloat { getLayoutGuide().layoutFrame.width } | |
var smallSide: CGFloat { | |
safeRect.width < safeRect.height ? safeRect.width : safeRect.height | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment