feat: Improve scroll indicator with tons of rectangles
This commit is contained in:
+52
-18
@@ -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
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user