This commit is contained in:
DDIsFriend
2023-08-18 17:28:57 +08:00
commit f0e8a1709d
4282 changed files with 192396 additions and 0 deletions

View File

@@ -0,0 +1,214 @@
//
// QLViewArray+QuickLayout.swift
// QuickLayout
//
// Created by Daniel Huri on 11/20/17.
//
import Foundation
import UIKit
// MARK: Multiple Views in Array
public extension Array where Element: QLView {
/**
All elements in the collection recieve constant value for the given edge.
- parameter edge: Should be used with *.width* or *.height*.
- parameter value: The size of the edge.
- parameter priority: Constraint's priority (default is *.required*).
- returns: The instance of the constraint that was applied (discardable).
*/
@discardableResult
func set(_ edge: QLAttribute, of value: CGFloat,
priority: QLPriority = .required) -> [NSLayoutConstraint] {
var constraints: [NSLayoutConstraint] = []
for view in self {
let constraint = view.set(edge, of: value)
constraints.append(constraint)
}
return constraints
}
/**
All elements in the collection recieve constant value for the given edges, using variadic parameter.
- parameter edges: Should be used with *.width* or *.height*.
- parameter value: The size of the edge.
- parameter priority: Constraint's priority (default is *.required*).
- returns: The instance of the constraint that was applied (discardable).
*/
@discardableResult
func set(_ edges: QLAttribute..., of value: CGFloat,
priority: QLPriority = .required) -> [QLMultipleConstraints] {
var constraintsArray: [QLMultipleConstraints] = []
for view in self {
let constraints = view.set(edges, to: value, priority: priority)
constraintsArray.append(constraints)
}
return constraintsArray
}
/**
Spread elements consecutively according to the given axis.
- parameter axis: The axis: *.vertically*, *horizontally*
- parameter stretchEdgesToSuperview: Decides whether the first and last items in the array must be clipped to their parent edges.
- parameter priority: Constraint's priority (default is *.required*).
- returns: Array of constraints that were applied (discardable)
*/
@discardableResult
func spread(_ axis: QLAxis, stretchEdgesToSuperview: Bool = false, offset: CGFloat = 0,
priority: QLPriority = .required) -> [NSLayoutConstraint] {
guard isValidForQuickLayout else {
return []
}
let attributes = axis.attributes
var constraints: [NSLayoutConstraint] = []
if stretchEdgesToSuperview {
let constraint = first!.layoutToSuperview(attributes.first, offset: offset)!
constraints.append(constraint)
}
for (index, view) in enumerated() {
guard index > 0 else {
continue
}
let previousView = self[index - 1]
let constraint = view.layout(attributes.first, to: attributes.second, of: previousView, offset: offset, priority: priority)!
constraints.append(constraint)
}
if stretchEdgesToSuperview {
let constraint = last!.layoutToSuperview(attributes.second, offset: -offset)!
constraints.append(constraint)
}
return constraints
}
/**
Layout elements to superview's axis
- parameter axis: The axis: *.vertically*, *horizontally*
- parameter offset: Additional side offset that must be applied (identical spacing from each side)
- parameter priority: Constraint's priority (default is *.required*).
- returns: Array of QLAxisConstraints - see definition (discardable)
*/
@discardableResult
func layoutToSuperview(axis: QLAxis, offset: CGFloat = 0,
priority: QLPriority = .required) -> [QLAxisConstraints] {
let attributes = axis.attributes
let firstConstraints = layoutToSuperview(attributes.first, offset: offset, priority: priority)
guard !firstConstraints.isEmpty else {
return []
}
let secondConstraints = layoutToSuperview(attributes.second, offset: -offset, priority: priority)
guard !secondConstraints.isEmpty else {
return []
}
var constraints: [QLAxisConstraints] = []
for (first, second) in zip(firstConstraints, secondConstraints) {
constraints.append(QLAxisConstraints(first: first, second: second))
}
return constraints
}
/**
Layout elements' edges to superview's edge (The same edge - top to top, bottom to bottom, etc...)
- parameter edge: The edge of the view / superview
- parameter ratio: The ratio of the edge in relation to the superview's (default is 1).
- parameter offset: Additional offset from that must be applied to the constraint (default is 0).
- parameter priority: Constraint's priority (default is *.required*).
- returns: Array of applied constraints - see definition (discardable)
*/
@discardableResult
func layoutToSuperview(_ edge: QLAttribute, ratio: CGFloat = 1, offset: CGFloat = 0,
priority: QLPriority = .required) -> [NSLayoutConstraint] {
guard isValidForQuickLayout else {
return []
}
return layout(to: edge, of: first!.superview!, ratio: ratio, offset: offset, priority: priority)
}
/**
Layout elements' edges to to anchorView edge
- parameter firstEdge: The edge of the elements in the array
- parameter anchorEdge: The edge of the anchor view
- parameter anchorView: The anchor view
- 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 constraints (default is 0).
- parameter priority: Constraints' priority (default is *.required*).
- returns: Array of applied constraints - see definition (discardable)
*/
@discardableResult
func layout(_ firstEdge: QLAttribute? = nil, to anchorEdge: QLAttribute,
of anchorView: QLView, ratio: CGFloat = 1, offset: CGFloat = 0,
priority: QLPriority = .required) -> [NSLayoutConstraint] {
guard isValidForQuickLayout else {
return []
}
let edge: QLAttribute
if let firstEdge = firstEdge {
edge = firstEdge
} else {
edge = anchorEdge
}
var result: [NSLayoutConstraint] = []
for view in self {
let constraint = view.layout(edge, to: anchorEdge, of: anchorView, ratio: ratio, offset: offset, priority: priority)!
result.append(constraint)
}
return result
}
/**
Layout elements' multiple edges to to anchorView's same edges (top to top, bottom to bottom, etc...)
- parameter edges: The edges of the view - variadic parameter
- parameter anchorView: The anchor view
- 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 constraints (default is 0).
- parameter priority: Constraints' priority (default is *.required*).
- returns: Array of applied constraints, each element is of type QLMultipleConstraints - see definition (discardable)
*/
@discardableResult
func layout(_ edges: QLAttribute..., to anchorView: QLView,
ratio: CGFloat = 1, offset: CGFloat = 0,
priority: QLPriority = .required) -> [QLMultipleConstraints] {
guard !edges.isEmpty && isValidForQuickLayout else {
return []
}
// Avoid duplicities
let uniqueEdges = Set(edges)
var result: [QLMultipleConstraints] = []
for view in self {
var multipleConstraints: QLMultipleConstraints = [:]
for edge in uniqueEdges {
let constraint = view.layout(to: edge, of: anchorView, ratio: ratio, offset: offset, priority: priority)!
multipleConstraints[edge] = constraint
}
result.append(multipleConstraints)
}
return result
}
/** **PRIVATELY USED** to test for validation*/
var isValidForQuickLayout: Bool {
guard !isEmpty else {
print("\(String(describing: self)) Error in func: \(#function), Views collection is empty!")
return false
}
for view in self {
guard view.isValidForQuickLayout else {
print("\(String(describing: self)) Error in func: \(#function)")
return false
}
}
return true
}
}