refactored spacing algos since we are now not resizing rectangle heights based off of the tallest container in the row
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
parent
81f7341148
commit
fd8e68f1c3
@ -8,77 +8,28 @@
|
||||
import Foundation
|
||||
|
||||
struct ButtonGroupConstants {
|
||||
static let rowSpacingButton = 12.0
|
||||
static let rowSpacingTextLink = 12.0
|
||||
|
||||
static func getHorizontalSpacing(for primary: Buttonable, neighboring: Buttonable) -> CGFloat {
|
||||
let defaultSpace = 12.0
|
||||
//large button
|
||||
if let button = primary as? Button, button.size == .large {
|
||||
if let neighboringButton = neighboring as? Button, neighboringButton.size == .large {
|
||||
return 12.0
|
||||
} else if let neighboringTextLink = neighboring as? TextLink, neighboringTextLink.size == .large {
|
||||
return 16.0
|
||||
} else if let _ = neighboring as? TextLinkCaret {
|
||||
return 24.0
|
||||
} else {
|
||||
return defaultSpace
|
||||
}
|
||||
}
|
||||
//large text link
|
||||
else if let textLink = primary as? TextLink, textLink.size == .large {
|
||||
if let neighboringButton = neighboring as? Button, neighboringButton.size == .large {
|
||||
return 16.0
|
||||
} else if let _ = neighboring as? TextLinkCaret {
|
||||
return 24.0
|
||||
} else if let neighboringTextLink = neighboring as? TextLink, neighboringTextLink.size == .large {
|
||||
return 16.0
|
||||
} else {
|
||||
return defaultSpace
|
||||
}
|
||||
}
|
||||
//text link caret
|
||||
else if let _ = primary as? TextLinkCaret {
|
||||
if let _ = neighboring as? TextLinkCaret {
|
||||
return 24.0
|
||||
} else {
|
||||
return defaultSpace
|
||||
}
|
||||
}
|
||||
//small button
|
||||
else if let button = primary as? Button, button.size == .small {
|
||||
if let neighboringButton = neighboring as? Button, neighboringButton.size == .small {
|
||||
return 12.0
|
||||
} else if let neighboringTextLink = neighboring as? TextLink, neighboringTextLink.size == .small {
|
||||
return 16.0
|
||||
} else {
|
||||
return defaultSpace
|
||||
}
|
||||
}
|
||||
//small text link
|
||||
else if let textLink = primary as? TextLink, textLink.size == .small {
|
||||
if let neighboringTextLink = neighboring as? TextLink, neighboringTextLink.size == .small {
|
||||
return 16.0
|
||||
} else {
|
||||
return defaultSpace
|
||||
}
|
||||
}
|
||||
//return defaultSpace
|
||||
else {
|
||||
return defaultSpace
|
||||
}
|
||||
static let defaultSpace = 12.0
|
||||
|
||||
enum ButtonSpacingAxis {
|
||||
case horizontal, vertical
|
||||
}
|
||||
|
||||
static func getVerticalSpacing(for primary: Buttonable, neighboring: Buttonable) -> CGFloat {
|
||||
let defaultSpace = 12.0
|
||||
/// This will determine the spacing that will go between 2 buttonables either horizontally or vertically
|
||||
/// - Parameters:
|
||||
/// - axis: horizontal/vertical
|
||||
/// - primary: first buttonable
|
||||
/// - neighboring: next buttonable based off of axis
|
||||
/// - Returns: float value
|
||||
static func getSpacing(for axis: ButtonSpacingAxis, with primary: Buttonable, neighboring: Buttonable) -> CGFloat {
|
||||
|
||||
//large button
|
||||
if let button = primary as? Button, button.size == .large {
|
||||
if let neighboringButton = neighboring as? Button, neighboringButton.size == .large {
|
||||
return 12.0
|
||||
return axis == .horizontal ? 12.0 : 12.0
|
||||
} else if neighboring is TextLinkCaret {
|
||||
return axis == .horizontal ? 24.0 : 24.0
|
||||
} else if let neighboringTextLink = neighboring as? TextLink, neighboringTextLink.size == .large {
|
||||
return 16.0
|
||||
} else if let _ = neighboring as? TextLinkCaret {
|
||||
return 24.0
|
||||
return axis == .horizontal ? 16.0 : 16.0
|
||||
} else {
|
||||
return defaultSpace
|
||||
}
|
||||
@ -86,11 +37,11 @@ struct ButtonGroupConstants {
|
||||
//large text link
|
||||
else if let textLink = primary as? TextLink, textLink.size == .large {
|
||||
if let neighboringButton = neighboring as? Button, neighboringButton.size == .large {
|
||||
return 16.0
|
||||
} else if let _ = neighboring as? TextLinkCaret {
|
||||
return 24.0
|
||||
return axis == .horizontal ? 16.0 : 16.0
|
||||
} else if neighboring is TextLinkCaret {
|
||||
return axis == .horizontal ? 24.0 : 24.0
|
||||
} else if let neighboringTextLink = neighboring as? TextLink, neighboringTextLink.size == .large {
|
||||
return 24.0
|
||||
return axis == .horizontal ? 16.0 : 24.0
|
||||
} else {
|
||||
return defaultSpace
|
||||
}
|
||||
@ -98,11 +49,11 @@ struct ButtonGroupConstants {
|
||||
//text link caret
|
||||
else if let _ = primary as? TextLinkCaret {
|
||||
if let neighboringButton = neighboring as? Button, neighboringButton.size == .large {
|
||||
return 16.0
|
||||
return axis == .horizontal ? 24.0 : 24.0
|
||||
} else if let _ = neighboring as? TextLinkCaret {
|
||||
return 24.0
|
||||
return axis == .horizontal ? 24.0 : 24.0
|
||||
} else if let neighboringTextLink = neighboring as? TextLink, neighboringTextLink.size == .large {
|
||||
return 24.0
|
||||
return axis == .horizontal ? 24.0 : 24.0
|
||||
} else {
|
||||
return defaultSpace
|
||||
}
|
||||
@ -110,9 +61,9 @@ struct ButtonGroupConstants {
|
||||
//small button
|
||||
else if let button = primary as? Button, button.size == .small {
|
||||
if let neighboringButton = neighboring as? Button, neighboringButton.size == .small {
|
||||
return 12.0
|
||||
return axis == .horizontal ? 12.0 : 12.0
|
||||
} else if let neighboringTextLink = neighboring as? TextLink, neighboringTextLink.size == .small {
|
||||
return 24.0
|
||||
return axis == .horizontal ? 16.0 : 24.0
|
||||
} else {
|
||||
return defaultSpace
|
||||
}
|
||||
@ -120,9 +71,9 @@ struct ButtonGroupConstants {
|
||||
//small text link
|
||||
else if let textLink = primary as? TextLink, textLink.size == .small {
|
||||
if let neighboringTextLink = neighboring as? TextLink, neighboringTextLink.size == .small {
|
||||
return 32.0
|
||||
} else if let neighboringButton = neighboring as? Button, neighboringButton.size == .small {
|
||||
return 24.0
|
||||
return axis == .horizontal ? 16.0 : 24.0
|
||||
} else if let _ = neighboring as? Button {
|
||||
return axis == .horizontal ? 16.0 : 32.0
|
||||
} else {
|
||||
return defaultSpace
|
||||
}
|
||||
@ -133,4 +84,54 @@ struct ButtonGroupConstants {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
|
||||
/// Gets the tallest buttonables within the row
|
||||
/// - Parameter row: Row that includes the attributes
|
||||
/// - Returns: Array of [ButtonLayoutAttributes] of the tallest items
|
||||
private static func getTallestAttributes(for row: ButtonCollectionViewRow) -> [ButtonLayoutAttributes] {
|
||||
var height = 0.0
|
||||
var foundIndexes:[Int] = []
|
||||
for (index, attribute) in row.attributes.enumerated() {
|
||||
if attribute.frame.height >= height {
|
||||
height = attribute.frame.height
|
||||
foundIndexes.append(index)
|
||||
}
|
||||
}
|
||||
return foundIndexes.compactMap { row.attributes[$0] }
|
||||
}
|
||||
|
||||
|
||||
/// Gets the vertical spacing that will go between rows.
|
||||
/// - Parameters:
|
||||
/// - row: Primary row that the space will go between
|
||||
/// - neighboringRow: Secondary row that will be below the Primary
|
||||
/// - Returns: Amount of space that should live between these rows based off of the items. The largest space will win when the comparison occurs.
|
||||
static func getVerticalSpacing(for row: ButtonCollectionViewRow, neighboringRow: ButtonCollectionViewRow?) -> CGFloat {
|
||||
// if the neighboringRow is nil, this is the last row in the collection
|
||||
// so return no space
|
||||
guard let neighboringRow else { return 0.0 }
|
||||
|
||||
let primaryTallestAttributes = getTallestAttributes(for: row)
|
||||
let neighboringTallestAttributes = getTallestAttributes(for: neighboringRow)
|
||||
|
||||
if primaryTallestAttributes.count > 0 && neighboringTallestAttributes.count > 0 {
|
||||
// If there is a tie for “tallest child,” the tiebreaker criteria is to refer to the child with the larger space requirement (for vertical spacing).
|
||||
var largestVerticalSpace = defaultSpace
|
||||
|
||||
primaryTallestAttributes.forEach { primaryAttribute in
|
||||
neighboringTallestAttributes.forEach { neighboringTallestAttribute in
|
||||
let space = getSpacing(for: .vertical, with: primaryAttribute.buttonable!, neighboring: neighboringTallestAttribute.buttonable!)
|
||||
if space > largestVerticalSpace {
|
||||
largestVerticalSpace = space
|
||||
}
|
||||
}
|
||||
}
|
||||
return largestVerticalSpace
|
||||
}
|
||||
else {
|
||||
return defaultSpace
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ class ButtonCollectionViewRow {
|
||||
func add(attribute: ButtonLayoutAttributes) {
|
||||
attributes.append(attribute)
|
||||
}
|
||||
|
||||
|
||||
var hasButtons: Bool {
|
||||
attributes.contains(where: { $0.isButton })
|
||||
}
|
||||
@ -33,7 +33,7 @@ class ButtonCollectionViewRow {
|
||||
var rowHeight: CGFloat {
|
||||
attributes.compactMap{$0.frame.height}.max() ?? 0
|
||||
}
|
||||
|
||||
|
||||
var maxHeightIndexPath: IndexPath {
|
||||
let maxHeight = rowHeight
|
||||
return attributes.first(where: {$0.frame.height == maxHeight})!.indexPath
|
||||
@ -112,7 +112,8 @@ class ButtonCollectionViewRow {
|
||||
for attribute in attributes {
|
||||
attribute.frame.origin.x = offset
|
||||
if attribute.frame.height < height {
|
||||
attribute.frame.size.height = height
|
||||
//recalibrate the y to vertically center align rect
|
||||
attribute.frame.origin.y += (height - attribute.frame.size.height) / 2
|
||||
}
|
||||
offset += attribute.frame.width + attribute.spacing
|
||||
}
|
||||
@ -130,11 +131,20 @@ protocol ButtongGroupPositionLayoutDelegate: AnyObject {
|
||||
|
||||
class ButtonLayoutAttributes: UICollectionViewLayoutAttributes{
|
||||
var spacing: CGFloat = 0
|
||||
var isButton: Bool = false
|
||||
|
||||
var buttonable: Buttonable?
|
||||
|
||||
var isButton: Bool {
|
||||
guard buttonable is Button else { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
convenience init(spacing: CGFloat,
|
||||
buttonable: Buttonable,
|
||||
forCellWith indexPath: IndexPath) {
|
||||
self.init(forCellWith: indexPath)
|
||||
self.spacing = spacing
|
||||
self.buttonable = buttonable
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,13 +228,12 @@ class ButtonGroupPositionLayout: UICollectionViewLayout {
|
||||
let neighbor = delegate.collectionView(collectionView, buttonableAtIndexPath: IndexPath(item: nextItem, section: section))
|
||||
|
||||
// get the spacing to go between the current and next buttonable
|
||||
itemSpacing = ButtonGroupConstants.getHorizontalSpacing(for: itemButtonable, neighboring: neighbor)
|
||||
itemSpacing = ButtonGroupConstants.getSpacing(for: .horizontal, with: itemButtonable, neighboring: neighbor)
|
||||
}
|
||||
|
||||
// create the custom layout attribute
|
||||
let attributes = ButtonLayoutAttributes(spacing: itemSpacing, forCellWith: indexPath)
|
||||
let attributes = ButtonLayoutAttributes(spacing: itemSpacing, buttonable: itemButtonable, forCellWith: indexPath)
|
||||
attributes.frame = CGRect(x: 0, y: 0, width: itemSize.width, height: itemSize.height)
|
||||
attributes.isButton = isButton(buttonable: itemButtonable)
|
||||
|
||||
// add it to the array
|
||||
rows.last?.add(attribute: attributes)
|
||||
@ -247,7 +256,8 @@ class ButtonGroupPositionLayout: UICollectionViewLayout {
|
||||
var rowSpacing = 0.0
|
||||
|
||||
if item > 0 {
|
||||
rowSpacing = 12.0
|
||||
let prevRow = rows[item - 1]
|
||||
rowSpacing = ButtonGroupConstants.getVerticalSpacing(for: prevRow, neighboringRow: row)
|
||||
row.rowY = layoutHeight + rowSpacing
|
||||
layoutHeight += rowSpacing
|
||||
}
|
||||
@ -265,14 +275,6 @@ class ButtonGroupPositionLayout: UICollectionViewLayout {
|
||||
itemCache = rowAttributes
|
||||
|
||||
}
|
||||
|
||||
func isButton(buttonable: Buttonable) -> Bool{
|
||||
if let _ = buttonable as? Button {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
override func layoutAttributesForElements(in rect: CGRect)-> [UICollectionViewLayoutAttributes]? {
|
||||
var visibleLayoutAttributes: [UICollectionViewLayoutAttributes] = []
|
||||
|
||||
Loading…
Reference in New Issue
Block a user