Compare commits
2 Commits
develop
...
mbruce/bre
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d83052fd48 | ||
|
|
3a47583c38 |
@ -57,20 +57,28 @@ final class BreadcrumbCellItem: UICollectionViewCell {
|
|||||||
///Configuring the cell with default setup
|
///Configuring the cell with default setup
|
||||||
private func setUp() {
|
private func setUp() {
|
||||||
separator.textColorConfiguration = textColorConfiguration.eraseToAnyColorable()
|
separator.textColorConfiguration = textColorConfiguration.eraseToAnyColorable()
|
||||||
contentView.addSubview(stackView)
|
// contentView.addSubview(stackView)
|
||||||
stackView.pinToSuperView()
|
// stackView.pinToSuperView()
|
||||||
separator.backgroundColor = .clear
|
separator.backgroundColor = .clear
|
||||||
}
|
}
|
||||||
|
|
||||||
///Updating the breadCrumbItem and UI based on the selected flag along with the surface
|
///Updating the breadCrumbItem and UI based on the selected flag along with the surface
|
||||||
func update(surface: Surface, hideSlash: Bool, breadCrumbItem: BreadcrumbItem) {
|
func update(surface: Surface, hideSlash: Bool, breadCrumbItem: BreadcrumbItem) {
|
||||||
separator.surface = surface
|
contentView.subviews.forEach { $0.removeFromSuperview() }
|
||||||
breadCrumbItem.surface = surface
|
contentView.addSubview(breadCrumbItem)
|
||||||
stackView.addArrangedSubview(separator)
|
breadCrumbItem.pinToSuperView()
|
||||||
stackView.addArrangedSubview(breadCrumbItem)
|
|
||||||
stackView.setCustomSpacing(VDSLayout.Spacing.space1X.value, after: separator)
|
// separator.surface = surface
|
||||||
separator.textColor = textColorConfiguration.getColor(surface)
|
// breadCrumbItem.surface = surface
|
||||||
separator.isHidden = hideSlash
|
// separator.removeFromSuperview()
|
||||||
|
// self.breadCrumbItem?.removeFromSuperview()
|
||||||
|
//
|
||||||
|
//// stackView.addArrangedSubview(separator)
|
||||||
|
// stackView.addArrangedSubview(breadCrumbItem)
|
||||||
|
//// stackView.setCustomSpacing(VDSLayout.Spacing.space1X.value, after: separator)
|
||||||
|
//
|
||||||
|
// separator.textColor = textColorConfiguration.getColor(surface)
|
||||||
|
// separator.isHidden = hideSlash
|
||||||
self.breadCrumbItem = breadCrumbItem
|
self.breadCrumbItem = breadCrumbItem
|
||||||
layoutIfNeeded()
|
layoutIfNeeded()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import Combine
|
|||||||
/// Breadcrumb contains text with a separator by default, highlights text in bold without a separator if selected.
|
/// Breadcrumb contains text with a separator by default, highlights text in bold without a separator if selected.
|
||||||
@objc (VDSBreadcrumbItem)
|
@objc (VDSBreadcrumbItem)
|
||||||
open class BreadcrumbItem: ButtonBase {
|
open class BreadcrumbItem: ButtonBase {
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Initializers
|
// MARK: - Initializers
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -34,19 +34,38 @@ open class BreadcrumbItem: ButtonBase {
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Public Properties
|
// MARK: - Public Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
open var hideSlash: Bool = false { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
/// TextStyle used on the titleLabel.
|
/// TextStyle used on the titleLabel.
|
||||||
open override var textStyle: TextStyle { isSelected ? TextStyle.boldBodySmall : TextStyle.bodySmall }
|
open override var textStyle: TextStyle { isSelected ? TextStyle.boldBodySmall : TextStyle.bodySmall }
|
||||||
|
|
||||||
/// UIColor used on the titleLabel text.
|
/// UIColor used on the titleLabel text.
|
||||||
open override var textColor: UIColor {
|
open override var textColor: UIColor {
|
||||||
textColorConfiguration.getColor(self)
|
textColorConfiguration.getColor(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override var textAttributes: [any LabelAttributeModel]? {
|
||||||
|
guard hideSlash else { return nil }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
open override var text: String? {
|
||||||
|
get { hideSlash ? super.text : "/ \(super.text ?? "")"}
|
||||||
|
set { super.text = newValue }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The natural size for the receiving view, considering only properties of the view itself.
|
||||||
/// The natural size for the receiving view, considering only properties of the view itself.
|
/// The natural size for the receiving view, considering only properties of the view itself.
|
||||||
open override var intrinsicContentSize: CGSize {
|
open override var intrinsicContentSize: CGSize {
|
||||||
return titleLabel?.intrinsicContentSize ?? super.intrinsicContentSize
|
guard let titleLabel else { return super.intrinsicContentSize }
|
||||||
|
// Calculate the titleLabel's intrinsic content size
|
||||||
|
let labelSize = titleLabel.sizeThatFits(CGSize(width: self.frame.width, height: CGFloat.greatestFiniteMagnitude))
|
||||||
|
// Adjust the size if needed (add any additional padding if your design requires)
|
||||||
|
let adjustedSize = CGSize(width: labelSize.width + contentEdgeInsets.left + contentEdgeInsets.right,
|
||||||
|
height: labelSize.height + contentEdgeInsets.top + contentEdgeInsets.bottom)
|
||||||
|
return adjustedSize
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Private Properties
|
// MARK: - Private Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -15,11 +15,21 @@ import Combine
|
|||||||
@objc(VDSBreadcrumbs)
|
@objc(VDSBreadcrumbs)
|
||||||
open class Breadcrumbs: View {
|
open class Breadcrumbs: View {
|
||||||
|
|
||||||
|
struct BreadcrumbsSpacerConfig: ButtonGroupSpaceable {
|
||||||
|
func getSpacing(for axis: NSLayoutConstraint.Axis, with primary: ButtonBase, neighboring: ButtonBase) -> CGFloat {
|
||||||
|
VDSLayout.Spacing.space1X.value
|
||||||
|
}
|
||||||
|
|
||||||
|
func getVerticalSpacing(for row: ButtonCollectionViewRow, neighboringRow: ButtonCollectionViewRow?) -> CGFloat {
|
||||||
|
VDSLayout.Spacing.space1X.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Public Properties
|
// MARK: - Public Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
/// Array of ``BreadcrumbItem`` views for the Breadcrumbs.
|
/// Array of ``BreadcrumbItem`` views for the Breadcrumbs.
|
||||||
open var breadcrumbs: [BreadcrumbItem] = [] { didSet { setNeedsUpdate() } }
|
open var breadcrumbs: [BreadcrumbItem] = [] { didSet { collectionView.buttons = breadcrumbs } }
|
||||||
|
|
||||||
/// Array of ``BreadcurmbItemModel`` you are wanting to show.
|
/// Array of ``BreadcurmbItemModel`` you are wanting to show.
|
||||||
open var breadcrumbModels: [BreadcrumbItemModel] = [] { didSet { updateBreadcrumbItems() } }
|
open var breadcrumbModels: [BreadcrumbItemModel] = [] { didSet { updateBreadcrumbItems() } }
|
||||||
@ -55,19 +65,23 @@ open class Breadcrumbs: View {
|
|||||||
$0.scrollDirection = .vertical
|
$0.scrollDirection = .vertical
|
||||||
}
|
}
|
||||||
|
|
||||||
///Collectionview to render Breadcrumb Items
|
// ///Collectionview to render Breadcrumb Items
|
||||||
private lazy var collectionView: SelfSizingCollectionView = {
|
// private lazy var collectionView: SelfSizingCollectionView = {
|
||||||
let collectionView = SelfSizingCollectionView(frame: .zero, collectionViewLayout: layout)
|
// let collectionView = SelfSizingCollectionView(frame: .zero, collectionViewLayout: layout)
|
||||||
collectionView.isScrollEnabled = false
|
// collectionView.isScrollEnabled = false
|
||||||
collectionView.translatesAutoresizingMaskIntoConstraints = false
|
// collectionView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
collectionView.delegate = self
|
// collectionView.delegate = self
|
||||||
collectionView.dataSource = self
|
// collectionView.dataSource = self
|
||||||
collectionView.showsHorizontalScrollIndicator = false
|
// collectionView.showsHorizontalScrollIndicator = false
|
||||||
collectionView.showsVerticalScrollIndicator = false
|
// collectionView.showsVerticalScrollIndicator = false
|
||||||
collectionView.register(BreadcrumbCellItem.self, forCellWithReuseIdentifier: BreadcrumbCellItem.identifier)
|
// collectionView.register(BreadcrumbCellItem.self, forCellWithReuseIdentifier: BreadcrumbCellItem.identifier)
|
||||||
collectionView.backgroundColor = .clear
|
// collectionView.backgroundColor = .clear
|
||||||
return collectionView
|
// return collectionView
|
||||||
}()
|
// }()
|
||||||
|
private var collectionView = ButtonGroup().with {
|
||||||
|
$0.alignment = .left
|
||||||
|
$0.spacerConfiguration = BreadcrumbsSpacerConfig()
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Private Methods
|
// MARK: - Private Methods
|
||||||
@ -118,22 +132,22 @@ open class Breadcrumbs: View {
|
|||||||
/// Used to make changes to the View based off a change events or from local properties.
|
/// Used to make changes to the View based off a change events or from local properties.
|
||||||
open override func updateView() {
|
open override func updateView() {
|
||||||
super.updateView()
|
super.updateView()
|
||||||
collectionView.reloadData()
|
collectionView.surface = surface
|
||||||
}
|
}
|
||||||
|
|
||||||
open override func layoutSubviews() {
|
// open override func layoutSubviews() {
|
||||||
//Turn off the ability to execute updateView() in the super
|
// //Turn off the ability to execute updateView() in the super
|
||||||
//since we don't want an infinite loop
|
// //since we don't want an infinite loop
|
||||||
shouldUpdateView = false
|
// shouldUpdateView = false
|
||||||
super.layoutSubviews()
|
// super.layoutSubviews()
|
||||||
shouldUpdateView = true
|
// shouldUpdateView = true
|
||||||
|
//
|
||||||
// Accounts for any collection size changes
|
// // Accounts for any collection size changes
|
||||||
DispatchQueue.main.async { [weak self] in
|
// DispatchQueue.main.async { [weak self] in
|
||||||
guard let self else { return }
|
// guard let self else { return }
|
||||||
self.collectionView.collectionViewLayout.invalidateLayout()
|
// self.collectionView.collectionViewLayout.invalidateLayout()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Breadcrumbs: UICollectionViewDelegate, UICollectionViewDataSource {
|
extension Breadcrumbs: UICollectionViewDelegate, UICollectionViewDataSource {
|
||||||
|
|||||||
@ -111,6 +111,16 @@ open class ButtonGroup: View {
|
|||||||
$0.delegate = self
|
$0.delegate = self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal var spacerConfiguration: (any ButtonGroupSpaceable)? {
|
||||||
|
didSet {
|
||||||
|
if let spacerConfiguration {
|
||||||
|
positionLayout.spacerConfiguration = spacerConfiguration
|
||||||
|
}
|
||||||
|
collectionView.collectionViewLayout.invalidateLayout()
|
||||||
|
collectionView.reloadData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// CollectionView that renders the array of buttonBase obects.
|
/// CollectionView that renders the array of buttonBase obects.
|
||||||
fileprivate lazy var collectionView: SelfSizingCollectionView = {
|
fileprivate lazy var collectionView: SelfSizingCollectionView = {
|
||||||
|
|
||||||
|
|||||||
@ -6,21 +6,23 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
|
||||||
struct ButtonGroupConstants {
|
protocol ButtonGroupSpaceable {
|
||||||
static let defaultSpace = 12.0
|
func getSpacing(for axis: NSLayoutConstraint.Axis, with primary: ButtonBase, neighboring: ButtonBase) -> CGFloat
|
||||||
|
func getVerticalSpacing(for row: ButtonCollectionViewRow, neighboringRow: ButtonCollectionViewRow?) -> CGFloat
|
||||||
enum ButtonSpacingAxis {
|
}
|
||||||
case horizontal, vertical
|
|
||||||
}
|
struct ButtonGroupSpacerConstants: ButtonGroupSpaceable {
|
||||||
|
let defaultSpace = 12.0
|
||||||
|
|
||||||
/// This will determine the spacing that will go between 2 ButtonBases either horizontally or vertically
|
/// This will determine the spacing that will go between 2 ButtonBases either horizontally or vertically
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - axis: horizontal/vertical
|
/// - axis: horizontal/vertical
|
||||||
/// - primary: first ButtonBase
|
/// - primary: first ButtonBase
|
||||||
/// - neighboring: next ButtonBase based off of axis
|
/// - neighboring: next ButtonBase based off of axis
|
||||||
/// - Returns: float value
|
/// - Returns: float value
|
||||||
static func getSpacing(for axis: ButtonSpacingAxis, with primary: ButtonBase, neighboring: ButtonBase) -> CGFloat {
|
func getSpacing(for axis: NSLayoutConstraint.Axis, with primary: ButtonBase, neighboring: ButtonBase) -> CGFloat {
|
||||||
|
|
||||||
//large button
|
//large button
|
||||||
if let button = primary as? Button, button.size == .large {
|
if let button = primary as? Button, button.size == .large {
|
||||||
@ -90,7 +92,7 @@ struct ButtonGroupConstants {
|
|||||||
/// Gets the tallest ButtonBases within the row
|
/// Gets the tallest ButtonBases within the row
|
||||||
/// - Parameter row: Row that includes the attributes
|
/// - Parameter row: Row that includes the attributes
|
||||||
/// - Returns: Array of [ButtonLayoutAttributes] of the tallest items
|
/// - Returns: Array of [ButtonLayoutAttributes] of the tallest items
|
||||||
private static func getTallestAttributes(for row: ButtonCollectionViewRow) -> [ButtonLayoutAttributes] {
|
private func getTallestAttributes(for row: ButtonCollectionViewRow) -> [ButtonLayoutAttributes] {
|
||||||
var height = 0.0
|
var height = 0.0
|
||||||
var foundIndexes:[Int] = []
|
var foundIndexes:[Int] = []
|
||||||
for (index, attribute) in row.attributes.enumerated() {
|
for (index, attribute) in row.attributes.enumerated() {
|
||||||
@ -102,13 +104,12 @@ struct ButtonGroupConstants {
|
|||||||
return foundIndexes.compactMap { row.attributes[$0] }
|
return foundIndexes.compactMap { row.attributes[$0] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Gets the vertical spacing that will go between rows.
|
/// Gets the vertical spacing that will go between rows.
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - row: Primary row that the space will go between
|
/// - row: Primary row that the space will go between
|
||||||
/// - neighboringRow: Secondary row that will be below the Primary
|
/// - 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.
|
/// - 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 {
|
func getVerticalSpacing(for row: ButtonCollectionViewRow, neighboringRow: ButtonCollectionViewRow?) -> CGFloat {
|
||||||
// if the neighboringRow is nil, this is the last row in the collection
|
// if the neighboringRow is nil, this is the last row in the collection
|
||||||
// so return no space
|
// so return no space
|
||||||
guard let neighboringRow else { return 0.0 }
|
guard let neighboringRow else { return 0.0 }
|
||||||
|
|||||||
@ -146,6 +146,7 @@ class ButtonLayoutAttributes: UICollectionViewLayoutAttributes{
|
|||||||
class ButtonGroupPositionLayout: UICollectionViewLayout {
|
class ButtonGroupPositionLayout: UICollectionViewLayout {
|
||||||
|
|
||||||
weak var delegate: ButtongGroupPositionLayoutDelegate?
|
weak var delegate: ButtongGroupPositionLayoutDelegate?
|
||||||
|
var spacerConfiguration: ButtonGroupSpaceable = ButtonGroupSpacerConstants()
|
||||||
|
|
||||||
// Total height of the content. Will be used to configure the scrollview content
|
// Total height of the content. Will be used to configure the scrollview content
|
||||||
var layoutHeight: CGFloat = 0.0
|
var layoutHeight: CGFloat = 0.0
|
||||||
@ -226,7 +227,7 @@ class ButtonGroupPositionLayout: UICollectionViewLayout {
|
|||||||
let neighbor = delegate.collectionView(collectionView, buttonBaseAtIndexPath: IndexPath(item: nextItem, section: section))
|
let neighbor = delegate.collectionView(collectionView, buttonBaseAtIndexPath: IndexPath(item: nextItem, section: section))
|
||||||
|
|
||||||
// get the spacing to go between the current and next button
|
// get the spacing to go between the current and next button
|
||||||
itemSpacing = ButtonGroupConstants.getSpacing(for: .horizontal, with: itemButtonBase, neighboring: neighbor)
|
itemSpacing = spacerConfiguration.getSpacing(for: .horizontal, with: itemButtonBase, neighboring: neighbor)
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the custom layout attribute
|
// create the custom layout attribute
|
||||||
@ -255,7 +256,7 @@ class ButtonGroupPositionLayout: UICollectionViewLayout {
|
|||||||
|
|
||||||
if item > 0 {
|
if item > 0 {
|
||||||
let prevRow = rows[item - 1]
|
let prevRow = rows[item - 1]
|
||||||
rowSpacing = ButtonGroupConstants.getVerticalSpacing(for: prevRow, neighboringRow: row)
|
rowSpacing = spacerConfiguration.getVerticalSpacing(for: prevRow, neighboringRow: row)
|
||||||
row.rowY = layoutHeight + rowSpacing
|
row.rowY = layoutHeight + rowSpacing
|
||||||
layoutHeight += rowSpacing
|
layoutHeight += rowSpacing
|
||||||
}
|
}
|
||||||
@ -273,7 +274,7 @@ class ButtonGroupPositionLayout: UICollectionViewLayout {
|
|||||||
itemCache = rowAttributes
|
itemCache = rowAttributes
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override func layoutAttributesForElements(in rect: CGRect)-> [UICollectionViewLayoutAttributes]? {
|
override func layoutAttributesForElements(in rect: CGRect)-> [UICollectionViewLayoutAttributes]? {
|
||||||
var visibleLayoutAttributes: [UICollectionViewLayoutAttributes] = []
|
var visibleLayoutAttributes: [UICollectionViewLayoutAttributes] = []
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user