From 5d8de1fb3660f72758e05c2b4e6cf48358746591 Mon Sep 17 00:00:00 2001 From: Andrea Busi Date: Tue, 11 Feb 2025 14:59:46 +0100 Subject: [PATCH] feat: Improve scroll indicator with tons of rectangles --- .../SeismicNetworkScrollIndicatorView.swift | 70 ++++++++++++++----- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/Sources/Earthquake Network/Controllers/Seismic Networks/SeismicNetworkScrollIndicatorView.swift b/Sources/Earthquake Network/Controllers/Seismic Networks/SeismicNetworkScrollIndicatorView.swift index 4d7fb54..04f6c65 100644 --- a/Sources/Earthquake Network/Controllers/Seismic Networks/SeismicNetworkScrollIndicatorView.swift +++ b/Sources/Earthquake Network/Controllers/Seismic Networks/SeismicNetworkScrollIndicatorView.swift @@ -12,6 +12,8 @@ import CoreGraphics class SeismicNetworkScrollIndicatorView: UIView { + private static let HighlightColor: UIColor = .red + var seismics: [SeismicNetworkViewModel] = [] { didSet { setNeedsDisplay() @@ -34,28 +36,60 @@ class SeismicNetworkScrollIndicatorView: UIView { guard numberOfRectangles > 0 else { return } let context = UIGraphicsGetCurrentContext() - let rectWidth = rect.width - let rectHeight = rect.height / CGFloat(numberOfRectangles) + let rectStandardWidth = rect.width + let rectStandardHeight = rect.height / CGFloat(numberOfRectangles) + let rectHighlightedMinHeight: CGFloat = 4 + let smallRectangles = rectStandardHeight < 10 + let highlightIndex = seismics.firstIndex(where: { $0 == highlighted }) ?? 100_000 + + seismics.enumerated().forEach { index, seismic in - let yPosition = CGFloat(index) * rectHeight - let rectangle = CGRect(x: 0, y: yPosition, width: rectWidth, height: rectHeight) - - context?.setFillColor(seismic.colors.textColor.withAlphaComponent(0.3).cgColor) - context?.fill(rectangle) + // Disegniamo un rettangolo per ogni sisma, quello evidenziato deve avere un contorno rosso. + // Ci sono situazioni in cui ci sono molti sismi da mostrare, quindi in quel caso facciamo alcune modifiche: + // - usiamo un'altezza minma per il sisma evidenziato + // - per il sisma evidenziato, anche il contenuto è rosso (e non solo il bordo) + // - negli altri sismi, non mostriamo il bordo - // Se è il rettangolo evidenziato, disegniamo un bordo rosso - if let highlighted, seismic == highlighted { - let borderWidth: CGFloat = 2.0 - context?.setStrokeColor(UIColor.red.cgColor) - context?.setLineWidth(borderWidth) // Spessore del bordo - context?.stroke(rectangle.insetBy(dx: borderWidth / 2, dy: borderWidth / 2)) // Evita che il bordo venga tagliato + if highlightIndex == index { + // Stiamo disegnando il sisma evidenziato. + // Valutiamo se utilizzare l'altezza minima. + let rectHeight = smallRectangles ? rectHighlightedMinHeight : rectStandardHeight + let yPosition = CGFloat(index) * rectStandardHeight + let rectangle = CGRect(x: 0, y: yPosition, width: rectStandardWidth, height: rectHeight) + + let fillColor = smallRectangles ? Self.HighlightColor : seismic.colors.textColor.withAlphaComponent(0.3) + context?.setFillColor(fillColor.cgColor) + context?.fill(rectangle) + + if !smallRectangles { + // disegniamo il bordo solo se i rettangoli non sono piccoli + let borderWidth: CGFloat = 2.0 + context?.setStrokeColor(Self.HighlightColor.cgColor) + context?.setLineWidth(borderWidth) // Spessore del bordo + context?.stroke(rectangle.insetBy(dx: borderWidth / 2, dy: borderWidth / 2)) // Evita che il bordo venga tagliato + } } else { - // altrimenti un bordo grigio - let borderWidth: CGFloat = 0.5 - context?.setStrokeColor(AppTheme.Colors.gray.cgColor) - context?.setLineWidth(borderWidth) // Spessore del bordo - context?.stroke(rectangle) // Evita che il bordo venga tagliato + // Stiamo disegnando i sismi non evidenziati, utilizziamo sempre l'altezza predefinita + // Dobbiamo eventualmente calcolare un offset aggiuntivo, + // perchè il sisma evidenziato ha un'altezza maggiore (se i rettangoli sono piccoli) + let rectHeight = rectStandardHeight + let offset: CGFloat = (index > highlightIndex && smallRectangles) ? rectHighlightedMinHeight : 0 + let yPosition = CGFloat(index) * rectHeight + offset + let rectangle = CGRect(x: 0, y: yPosition, width: rectStandardWidth, height: rectHeight) + + let fillColor = seismic.colors.textColor.withAlphaComponent(0.3) + context?.setFillColor(fillColor.cgColor) + context?.fill(rectangle) + + if !smallRectangles { + // altrimenti un bordo grigio + let borderWidth: CGFloat = 0.5 + context?.setStrokeColor(AppTheme.Colors.gray.cgColor) + context?.setLineWidth(borderWidth) // Spessore del bordo + context?.stroke(rectangle) // Evita che il bordo venga tagliato + + } } } }