Οι δείκτες (ή μπάρες) προόδου (progress indicators or bars) βοηθούν τους χρήστες της εφαρμογής μας να γνωρίζουν ότι δεν έχει "κολλήσει", κατά την διάρκεια φόρτωσης δεδομένων ή άλλων διεργασιών που απαιτούν αρκετό χρόνο να εκτελεστούν.
Δεδομένου ότι η διάρκεια μιας διεργασίας είναι είτε γνωστή είτε άγνωστη σε εμάς ως developers, υπάρχουν δύο τύποι progress indicators:
Determinate (καθορισμένος), για εργασίες με "μετρήσιμη" διάρκεια όπως η μετατροπή ή λήψη ενός ενός αρχείου.
Indeterminate (μη καθορισμένος), για εργασίες που δεν γνωρίζουμε εκ των προτέρων πόσο μπορεί να διαρκέσουν, όπως ο συγχρονισμός πολύπλοκων δεδομένων.
Μονο για το MacOS;
Σύμφωνα με το documentation της Apple, τη στιγμή που γράφω αυτό το άρθρο, η ατέρμονη κίνηση χρήσιμη σε εμάς στην περίπτωση μη καθορισμένης εργασίας, είναι διαθέσιμη μόνο στο MacOS και όχι στο iOS.
Για το λόγο αυτό θα δημιουργήσουμε έναν δικό μας με το πιο devItEasy τρόπο.
import UIKit
/// Creates an *indeterminate* indicator for iOS.
/// Suitable for unquantifiable tasks, such as loading or synchronizing complex data.
class IndeterminateIndicator: UIView {
var barLength: CGFloat?
var barHeight: CGFloat?
var barColor: UIColor?
var lineLength: CGFloat?
var lineHeight: CGFloat?
var lineCenter: CGFloat?
var lineColor: UIColor?
var lineSpeed: Double?
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override func draw(_ rect: CGRect) {
let barLength: CGFloat = self.barLength ?? self.frame.width
let barHeight: CGFloat = self.barLength ?? self.frame.height
let lineLength: CGFloat = self.lineLength ?? barLength / 2
let lineHeight: CGFloat = self.lineHeight ?? barHeight / 2
let lineY: CGFloat = self.lineCenter ?? lineHeight
let lineColor: UIColor = self.barColor ?? .red
let lineSpeed: Double = self.lineSpeed ?? 1.0
let path = UIBezierPath()
path.move(to: CGPoint(x: -lineLength, y: lineY))
path.addLine(to: CGPoint(x: 0, y: lineY))
let shape = CAShapeLayer()
shape.path = path.cgPath
shape.strokeColor = lineColor.cgColor
shape.lineWidth = lineHeight
self.layer.addSublayer(shape)
let animation = CABasicAnimation(keyPath: "position.x")
animation.fromValue = 0
animation.toValue = barLength + lineLength
animation.duration = lineSpeed
animation.repeatCount = .greatestFiniteMagnitude
shape.add(animation, forKey: "play")
}
}
Comments