Files
OrderScheduling/Pods/SwiftEntryKit/Source/Extensions/QuickLayout/UIView+QuickLayout.swift
DDIsFriend f0e8a1709d initial
2023-08-18 17:28:57 +08:00

268 lines
13 KiB
Swift

//
// QLView+QuickLayout.swift
// QuickLayout
//
// Created by Daniel Huri on 11/19/17.
//
import Foundation
import UIKit
public extension QLView {
/**
Set constant value of an edge.
Should be used with *width* or *height*
- parameter edge: Edge type.
- parameter value: Edge size.
- parameter relation: Relation to the given constant value (default is *.equal*).
- parameter ratio: Ratio of the cconstant constraint to actual given value (default is *1*)
- parameter priority: Constraint's priority (default is *.required*).
- returns: The applied constraint (discardable).
*/
@discardableResult
func set(_ edge: QLAttribute, of value: CGFloat, relation: QLRelation = .equal,
ratio: CGFloat = 1.0, priority: QLPriority = .required) -> NSLayoutConstraint {
if translatesAutoresizingMaskIntoConstraints {
translatesAutoresizingMaskIntoConstraints = false
}
let constraint = NSLayoutConstraint(item: self, attribute: edge, relatedBy: relation, toItem: nil, attribute: .notAnAttribute, multiplier: ratio, constant: value)
constraint.priority = priority
addConstraint(constraint)
return constraint
}
/**
Set constant value for multiple edges simultaniously, using variadic parameter.
Should be used with *width* or *height*
- parameter edges: Edge types.
- parameter value: Edges size.
- parameter priority: Constraint's priority (default is *.required*).
- returns: The applied constraints in QLMultipleConstraints - see definition (discardable).
*/
@discardableResult
func set(_ edges: QLAttribute..., of value: CGFloat, relation: QLRelation = .equal,
ratio: CGFloat = 1.0, priority: QLPriority = .required) -> QLMultipleConstraints {
return set(edges, to: value, relation: relation, ratio: ratio, priority: priority)
}
/** **PRIVATELY USED** AS A REPLACEMENT for the variadic version for the method*/
@discardableResult
func set(_ edges: [QLAttribute], to value: CGFloat, relation: QLRelation = .equal,
ratio: CGFloat = 1.0, priority: QLPriority = .required) -> QLMultipleConstraints {
var constraints: QLMultipleConstraints = [:]
let uniqueEdges = Set(edges)
for edge in uniqueEdges {
let constraint = set(edge, of: value, priority: priority)
constraints[edge] = constraint
}
return constraints
}
/**
Layout edge to another view's edge.
- You can optionally define relation, ratio, constant and priority (each gets a default value)
- For example - Can be used to align self *left* edge to the *right* of another view.
- *self* and *view* must be directly connected (siblings / child-parent) in the view hierarchy.
- *superview* must not be *nil*.
- parameter edge: The edge of the first view. If not sent or *nil* - The function automatically assumes *edge* to be *otherEdge*
- parameter otherEdge: The edge of the second view.
- parameter view: The second view that self must be aligned with.
- parameter relation: The relation of the first edge to the second edge (default is .equal)
- parameter ratio: The ratio of the edge in relative to the superview edge (default is 1).
- parameter offset: Additional offset which is applied to the constraint (default is 0).
- parameter priority: Constraint's priority (default is *.required*).
- returns: The instance of the constraint that was applied (discardable). nil if method failed to apply the constraint.
*/
@discardableResult
func layout(_ edge: QLAttribute? = nil, to otherEdge: QLAttribute, of view: QLView,
relation: QLRelation = .equal, ratio: CGFloat = 1.0, offset: CGFloat = 0,
priority: QLPriority = .required) -> NSLayoutConstraint? {
guard isValidForQuickLayout else {
print("\(String(describing: self)) Error in func: \(#function)")
return nil
}
let constraint = NSLayoutConstraint(item: self, attribute: edge ?? otherEdge, relatedBy: relation, toItem: view, attribute: otherEdge, multiplier: ratio, constant: offset)
constraint.priority = priority
superview!.addConstraint(constraint)
return constraint
}
/**
Layout multiple edges of the view to the corresonding edges of another given view.
- You can optionally define relation, ratio, constant and priority (each gets a default value)
- For example - Can be used to align self *left* and *right* edges the same edge of another given view.
- *self* and *view* must be directly connected (siblings / child-parent) in the view hierarchy.
- *superview* must not be *nil*.
- parameter edges: The view edges
- parameter view: Another view that self must be aligned with.
- parameter relation: The relation of the edges. Can be applied to *.width* or *height* for example. (default is *.equal*).
- parameter ratio: The ratio of the edges to the other view edges (default is 1).
- parameter offset: Additional offset which is applied to each of the constraints (default is 0).
- parameter priority: Constraints' priority (default is *.required*).
- returns: The instance of the constraint that was applied (discardable). *nil* if the method failed to apply the constraint.
*/
@discardableResult
func layout(_ edges: QLAttribute..., to view: QLView, relation: QLRelation = .equal,
ratio: CGFloat = 1.0, offset: CGFloat = 0,
priority: QLPriority = .required) -> QLMultipleConstraints {
var constraints: QLMultipleConstraints = [:]
guard isValidForQuickLayout else {
print("\(String(describing: self)) Error in func: \(#function)")
return constraints
}
let uniqueEdges = Set(edges)
for edge in uniqueEdges {
let constraint = NSLayoutConstraint(item: self, attribute: edge, relatedBy: relation, toItem: view, attribute: edge, multiplier: ratio, constant: offset)
constraint.priority = priority
superview!.addConstraint(constraint)
constraints[edge] = constraint
}
return constraints
}
/**
Layout edge to the same edge of superview.
- Example of usage: *view.layoutToSuperview(.top)* makes *view* cling to the *top* of it's *superview*.
- You can optionally define ratio, constant and priority (each gets a default value)
- *superview* must not be *nil*.
- parameter edge: The edge (.width, .height, .left, .right, .leading, .trailing, etc...)
- parameter relation: The relation of the edge to the superview's corresponding edge (default is *.equal*)
- parameter ratio: The ratio of the edge in relative to the superview edge (default is 1).
- parameter offset: Additional offset from that can be applied to the constraint (default is 0).
- parameter priority: Constraint's priority (default is *.required*).
- returns: The instance of the constraint that was applied (discardable). Nil if method failed to apply constraint.
*/
@discardableResult
func layoutToSuperview(_ edge: QLAttribute, relation: QLRelation = .equal,
ratio: CGFloat = 1, offset: CGFloat = 0,
priority: QLPriority = .required) -> NSLayoutConstraint? {
guard isValidForQuickLayout else {
print("\(String(describing: self)) Error in func: \(#function)")
return nil
}
let constraint = NSLayoutConstraint(item: self, attribute: edge, relatedBy: relation, toItem: superview, attribute: edge, multiplier: ratio, constant: offset)
constraint.priority = priority
superview!.addConstraint(constraint)
return constraint
}
/**
Layout multiple edges to the same edges as superview, using variadic parameter.
Example for edges value:
- You can optionally define ratio, constant and priority (each gets a default value)
- *superview* must not be *nil*.
- parameter edges: The edges (.width, .height, .left, .right, .leading, .trailing, etc...)
- parameter relation: The relation of the edges to the superview's corresponding edges (default is *.equal*)
- parameter ratio: The ratio of the edges in relative to the superview edge (default is 1).
- parameter offset: Additional offset from that can be applied to the constraints (default is 0).
- parameter priority: Constraints' priority (default is *.required*).
- returns: The instance of QLMultipleConstraints - see type definition (discardable).
*/
@discardableResult
func layoutToSuperview(_ edges: QLAttribute..., relation: QLRelation = .equal,
ratio: CGFloat = 1, offset: CGFloat = 0,
priority: QLPriority = .required) -> QLMultipleConstraints {
var constraints: QLMultipleConstraints = [:]
guard !edges.isEmpty && isValidForQuickLayout else {
return constraints
}
let uniqueEdges = Set(edges)
for edge in uniqueEdges {
let constraint = NSLayoutConstraint(item: self, attribute: edge, relatedBy: relation, toItem: superview, attribute: edge, multiplier: ratio, constant: offset)
constraint.priority = priority
superview!.addConstraint(constraint)
constraints[edge] = constraint
}
return constraints
}
/**
Layout to one of the superview's axes.
- You can optionally define ratio, constant and priority (each gets a default value)
- *superview* must not be *nil*.
- parameter axis: The axis to which the view must be stretched (horizontally or vertically)
- parameter offset: Represents an additional edge offset from that can be applied to the constraints (default is 0)
- parameter priority: Represents constraint's priority (default is *.required*)
- returns: The instance of the constraint that was applied (discardable).
*/
@discardableResult
func layoutToSuperview(axis: QLAxis, offset: CGFloat = 0,
priority: QLPriority = .required) -> QLAxisConstraints? {
let attributes = axis.attributes
guard let first = layoutToSuperview(attributes.first, offset: offset, priority: priority) else {
return nil
}
guard let second = layoutToSuperview(attributes.second, offset: -offset, priority: priority) else {
return nil
}
return QLAxisConstraints(first: first, second: second)
}
/**
Size to superview with a given ratio and constant
- *superview* must not be *nil*.
- parameter ratio: The ratio of view to the size of superview.
- parameter offset: Represents an additional edge offset from that can be applied to the size (default is 0)
- parameter priority: Represents constraint's priority (default is *.required*)
- returns: The instance of QLSizeConstraints - see definition (discardable).
*/
@discardableResult
func sizeToSuperview(withRatio ratio: CGFloat = 1, offset: CGFloat = 0,
priority: QLPriority = .required) -> QLSizeConstraints? {
let size = layoutToSuperview(.width, .height, ratio: ratio, offset: offset, priority: priority)
guard !size.isEmpty else {
return nil
}
return QLSizeConstraints(width: size[.width]!, height: size[.height]!)
}
/**
Center in superview with an optional offset
- *superview* must not be *nil*.
- parameter offset: Represents an additional offset from the center (default is 0)
- parameter priority: Represents constraint's priority (default is *.required*)
- returns: The instance of QLCenterConstraints - see definition (discardable).
*/
@discardableResult
func centerInSuperview(offset: CGFloat = 0, priority: QLPriority = .required) -> QLCenterConstraints? {
let center = layoutToSuperview(.centerX, .centerY, offset: offset)
guard !center.isEmpty else {
return nil
}
return QLCenterConstraints(x: center[.centerX]!, y: center[.centerY]!)
}
/**
Fill superview totally (center and size to superview)
- *superview* must not be *nil*.
- parameter ratio: Ratio to the superview's size (default is 1)
- parameter offset: Offset from center (default is 0)
- parameter priority: Represents constraint's priority (default is *.required*)
- returns: The instance of QLFillConstraints - see definition (discardable).
*/
@discardableResult
func fillSuperview(withSizeRatio ratio: CGFloat = 1, offset: CGFloat = 0,
priority: QLPriority = .required) -> QLFillConstraints? {
guard let center = centerInSuperview(priority: priority) else {
return nil
}
guard let size = sizeToSuperview(withRatio: ratio, offset: offset, priority: priority) else {
return nil
}
return QLFillConstraints(center: center, size: size)
}
/** **PRIVATELY USED** to test for validation*/
var isValidForQuickLayout: Bool {
guard superview != nil else {
print("\(String(describing: self)):\(#function) - superview is unexpectedly nullified")
return false
}
if translatesAutoresizingMaskIntoConstraints {
translatesAutoresizingMaskIntoConstraints = false
}
return true
}
}