From ff0117dc1da8fc0d4818a8f593a952c75e9aab57 Mon Sep 17 00:00:00 2001 From: vasavk Date: Thu, 16 May 2024 16:55:00 +0530 Subject: [PATCH 1/3] Hide legend view when date indicators are empty --- VDS/Components/Calendar/Calendar.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VDS/Components/Calendar/Calendar.swift b/VDS/Components/Calendar/Calendar.swift index f7c1940c..fd3e3452 100644 --- a/VDS/Components/Calendar/Calendar.swift +++ b/VDS/Components/Calendar/Calendar.swift @@ -67,7 +67,7 @@ open class CalendarBase: Control, Changeable { //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- - internal var containerSize: CGSize { CGSize(width: 328, height: 376) } + internal var containerSize: CGSize { CGSize(width: 328, height: 336) } internal var calendar = Calendar.current private let cellItemSize = CGSize(width: 40, height: 40) @@ -358,7 +358,7 @@ extension CalendarBase: UICollectionViewDelegate, UICollectionViewDataSource, UI } public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { - return CGSize(width: collectionView.frame.size.width, height: footerHeight) + return CGSize(width: collectionView.frame.size.width, height: indicators.count > 0 ? footerHeight : 0) } public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { From 9c1b12810233d8918ad4a90545e9c35a26b74776 Mon Sep 17 00:00:00 2001 From: vasavk Date: Thu, 16 May 2024 17:06:01 +0530 Subject: [PATCH 2/3] Showing 3 variations of icons for date indicators for legend --- .../Calendar/CalendarFooterReusableView.swift | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/VDS/Components/Calendar/CalendarFooterReusableView.swift b/VDS/Components/Calendar/CalendarFooterReusableView.swift index f8432bda..1a402dc3 100644 --- a/VDS/Components/Calendar/CalendarFooterReusableView.swift +++ b/VDS/Components/Calendar/CalendarFooterReusableView.swift @@ -40,7 +40,9 @@ class CalendarFooterReusableView: UICollectionReusableView { $0.backgroundColor = .clear $0.delegate = self $0.dataSource = self - $0.register(LegendCollectionViewCell.self, forCellWithReuseIdentifier: LegendCollectionViewCell.identifier) + + $0.register(LegendCollectionViewCell.self, + forCellWithReuseIdentifier: LegendCollectionViewCell.identifier) } //-------------------------------------------------- @@ -160,7 +162,11 @@ private class LegendCollectionViewCell: UICollectionViewCell { func setupCell() { addSubview(stackView) stackView.pinToSuperView() - + } + + func updateView() { + stackView.arrangedSubviews.forEach { $0.removeFromSuperview() } + legendIndicator.layer.sublayers?.forEach { $0.removeFromSuperlayer() } legendIndicatorWrapper.addSubview(legendIndicator) legendIndicator.pinLeading().pinTrailing().width(8).height(8).pinCenterY() @@ -169,6 +175,7 @@ private class LegendCollectionViewCell: UICollectionViewCell { } func updateTitle(text: String, color: UIColor, surface: Surface, clearFullcircle: Bool, drawSemiCircle: Bool) { + updateView() title.surface = surface title.text = text title.textColor = textColorConfiguration.getColor(surface) From 44f3e7120881fb2f7df271dac70790686ac63f5c Mon Sep 17 00:00:00 2001 From: vasavk Date: Fri, 17 May 2024 15:27:27 +0530 Subject: [PATCH 3/3] legend alignment set to left and handling label overflow --- .../Calendar/CalendarFooterReusableView.swift | 80 ++++++++++++++++--- 1 file changed, 67 insertions(+), 13 deletions(-) diff --git a/VDS/Components/Calendar/CalendarFooterReusableView.swift b/VDS/Components/Calendar/CalendarFooterReusableView.swift index 1a402dc3..9547084f 100644 --- a/VDS/Components/Calendar/CalendarFooterReusableView.swift +++ b/VDS/Components/Calendar/CalendarFooterReusableView.swift @@ -20,17 +20,26 @@ class CalendarFooterReusableView: UICollectionReusableView { private var surface: Surface = .light private var items: [CalendarBase.CalendarIndicatorModel] = [] internal var containerSize: CGSize { CGSize(width: 304, height: 40) } - + internal var indicatorWidth = 8.0 + + var textLabel: Label = Label().with { + $0.translatesAutoresizingMaskIntoConstraints = false + $0.textAlignment = .left + $0.textStyle = .bodySmall + $0.numberOfLines = 1 + } + internal var containerView = View().with { $0.clipsToBounds = true } - private let flowLayout = UICollectionViewFlowLayout().with { + private let flowLayout = LeftAlignedCollectionViewFlowLayout().with { $0.estimatedItemSize = UICollectionViewFlowLayout.automaticSize $0.minimumLineSpacing = VDSLayout.space1X $0.minimumInteritemSpacing = VDSLayout.space4X $0.scrollDirection = .vertical } + open lazy var legendCollectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout).with { $0.isScrollEnabled = false $0.translatesAutoresizingMaskIntoConstraints = false @@ -45,6 +54,8 @@ class CalendarFooterReusableView: UICollectionReusableView { forCellWithReuseIdentifier: LegendCollectionViewCell.identifier) } + private var topConstraint: NSLayoutConstraint? + //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- @@ -66,18 +77,17 @@ class CalendarFooterReusableView: UICollectionReusableView { isAccessibilityElement = false addSubview(containerView) - containerView - .pinTopLessThanOrEqualTo(topAnchor, VDSLayout.space6X, .defaultLow) - .pinBottom() - .pinLeadingGreaterThanOrEqualTo(leadingAnchor, VDSLayout.space3X, .defaultHigh) - .pinTrailingLessThanOrEqualTo(trailingAnchor, VDSLayout.space3X, .defaultHigh) - .width(containerSize.width - (2*VDSLayout.space3X)) - .heightLessThanEqualTo(containerSize.height) + containerView.pinToSuperView() // legend Collection View containerView.addSubview(legendCollectionView) - legendCollectionView.pinTop().pinBottom().pinLeading().pinTrailing().pinCenterY().pinCenterX() - + legendCollectionView + .pinTopLessThanOrEqualTo(topAnchor, VDSLayout.space6X, .defaultLow) + .pinBottom() + .pinLeading(VDSLayout.space3X) + .pinTrailing(VDSLayout.space3X) + .width(containerSize.width - (2 * VDSLayout.space3X)) + .heightGreaterThanEqualTo(16) } /// Updating UI to show legend with titles. @@ -85,6 +95,15 @@ class CalendarFooterReusableView: UICollectionReusableView { self.items = indicators self.surface = surface legendCollectionView.reloadData() + + var height = legendCollectionView.collectionViewLayout.collectionViewContentSize.height + if height > 0 { + topConstraint?.isActive = false + height = height > containerSize.height ? containerSize.height : height + let top = containerSize.height - height + topConstraint = legendCollectionView.topAnchor.constraint(equalTo: topAnchor, constant: top) + topConstraint?.isActive = true + } } } @@ -107,6 +126,14 @@ extension CalendarFooterReusableView: UICollectionViewDelegate, UICollectionView drawSemiCircle: indexPath.row == 2) return cell } + + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + textLabel.text = items[indexPath.row].label + let intrinsicSize = textLabel.intrinsicContentSize + let cellwidth = intrinsicSize.width + indicatorWidth + VDSLayout.space2X + return .init(width: min(cellwidth, collectionView.frame.width), height: intrinsicSize.height) + } + } private class LegendCollectionViewCell: UICollectionViewCell { @@ -130,6 +157,7 @@ private class LegendCollectionViewCell: UICollectionViewCell { $0.translatesAutoresizingMaskIntoConstraints = false $0.backgroundColor = .clear } + private var legendIndicator: View = View().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.backgroundColor = .clear @@ -138,7 +166,8 @@ private class LegendCollectionViewCell: UICollectionViewCell { private lazy var stackView = UIStackView().with { $0.translatesAutoresizingMaskIntoConstraints = false - $0.distribution = .equalSpacing + $0.alignment = .fill + $0.distribution = .fill $0.spacing = VDSLayout.space2X $0.axis = .horizontal $0.backgroundColor = .clear @@ -146,6 +175,8 @@ private class LegendCollectionViewCell: UICollectionViewCell { private lazy var shapeLayer = CAShapeLayer() + internal var indicatorSize: CGSize { CGSize(width: 8, height: 8) } + //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- @@ -167,8 +198,9 @@ private class LegendCollectionViewCell: UICollectionViewCell { func updateView() { stackView.arrangedSubviews.forEach { $0.removeFromSuperview() } legendIndicator.layer.sublayers?.forEach { $0.removeFromSuperlayer() } + legendIndicatorWrapper.addSubview(legendIndicator) - legendIndicator.pinLeading().pinTrailing().width(8).height(8).pinCenterY() + legendIndicator.pinLeading().pinTrailing().width(indicatorSize.width).height(indicatorSize.height).pinCenterY() stackView.addArrangedSubview(legendIndicatorWrapper) stackView.addArrangedSubview(title) @@ -201,3 +233,25 @@ private class LegendCollectionViewCell: UICollectionViewCell { legendIndicator.layer.addSublayer(shapeLayer) } } + +class LeftAlignedCollectionViewFlowLayout: UICollectionViewFlowLayout { + + override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { + let attributes = super.layoutAttributesForElements(in: rect) + + var leftMargin = sectionInset.left + var maxY: CGFloat = -1.0 + attributes?.forEach { layoutAttribute in + if layoutAttribute.frame.origin.y >= maxY { + leftMargin = sectionInset.left + } + + layoutAttribute.frame.origin.x = leftMargin + + leftMargin += layoutAttribute.frame.width + minimumInteritemSpacing + maxY = max(layoutAttribute.frame.maxY , maxY) + } + + return attributes + } +}