Δημιουργία ατέρμονου progress bar για το iOS

By tgalanis , 13 October 2023
Swift progress bar

Οι δείκτες (ή μπάρες) προόδου (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