Prakhar Trivedi
Prakhar Trivedi

Reputation: 15

How to change UIProgressView tint colour as it approaches the end

So, I have a UIProgressView in a basic expense tracking app and I want to change its progress tint as it reaches the end from green to red progressively. I don't really know how to do this (I'm just starting out swift and Xcode).

This is how it should roughly work: My progress is calculated with this line:
let progress = Float(UserDefaults.standard.double(forKey: "spentThisMonth") / UserDefaults.standard.double(forKey: "monthlyExpenseLimit"))
progressView.progress = progress

Here I am dividing the amount the user has spent this month from the limit to get the progress. As the user approaches the limit, the progress tint turns red to indicate that the user should lower their expenditure.

This question is similar but I think its Objective-C, while I use Swift 5. Is there any way to do this, i.e is it possible? I am also new to Stack Overflow so I apologise in advance if I'm doing something wrong.

Upvotes: 1

Views: 1123

Answers (2)

DonMag
DonMag

Reputation: 77546

You can set the green / red tint color easily by using the progress value you've already calculated:

    let progress = Float(UserDefaults.standard.double(forKey: "spentThisMonth") / UserDefaults.standard.double(forKey: "monthlyExpenseLimit"))

    // progress is now a value between 0.0 and 1.0
    progressView.progress = progress

    let red = CGFloat(progress)
    let green = CGFloat(1.0 - progress)
    progressView.progressTintColor = UIColor(red: red, green: green, blue: 0.0, alpha: 1.0)

Here's a working example - each time you tap the screen, the progress will increment until it reaches 100%, at which time it will decrement back to Zero:

class ProgressTintViewController: UIViewController {
    
    let progressView = UIProgressView()
    let statsLabel = UILabel()
    
    var spentThisMonth: Float = 0
    var monthlyExpenseLimit: Float = 100
    var isAdding: Bool = true
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        progressView.translatesAutoresizingMaskIntoConstraints = false
        statsLabel.translatesAutoresizingMaskIntoConstraints = false
        
        view.addSubview(progressView)
        view.addSubview(statsLabel)
        
        let g = view.safeAreaLayoutGuide
        
        NSLayoutConstraint.activate([

            progressView.topAnchor.constraint(equalTo: g.topAnchor, constant: 80.0),
            progressView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            progressView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),

            statsLabel.topAnchor.constraint(equalTo: progressView.bottomAnchor, constant: 20.0),
            statsLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            statsLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),

        ])
        
        statsLabel.numberOfLines = 0
        
        let t = UITapGestureRecognizer(target: self, action: #selector(self.tapped))
        view.addGestureRecognizer(t)
        
        updateProgress()
    }

    @objc func tapped() -> Void {
        
        if isAdding {
            spentThisMonth += 10
        } else {
            spentThisMonth -= 10
        }

        updateProgress()
        
        if spentThisMonth >= monthlyExpenseLimit {
            spentThisMonth = monthlyExpenseLimit
            isAdding = false
        }
        
        if spentThisMonth <= 0 {
            spentThisMonth = 0
            isAdding = true
        }

    }
    
    func updateProgress() -> Void {
        
        //let progress = Float(UserDefaults.standard.double(forKey: "spentThisMonth") / UserDefaults.standard.double(forKey: "monthlyExpenseLimit"))
        // progress is now a value between 0.0 and 1.0
        
        let progress = spentThisMonth / monthlyExpenseLimit
        progressView.progress = progress

        let red = CGFloat(progress)
        let green = CGFloat(1.0 - progress)
        progressView.progressTintColor = UIColor(red: red, green: green, blue: 0.0, alpha: 1.0)

        var str = ""
        str += "Tap to change progress"
        str += "\n\n"
        str += "Spent This Month: \(spentThisMonth)"
        str += "\n"
        str += "Monthly Limit: \(monthlyExpenseLimit)"
        str += "\n"
        str += "Percent: \(progress)"
        
        statsLabel.text = str
        
    }
    
}

Upvotes: 1

Denis Kozhukhov
Denis Kozhukhov

Reputation: 1215

Sure it can be done using Swift. Here the code from answer made in Swift:

func changeSendProg(progress: CGFloat) {
    let redBlueValue: CGFloat = (255 - (255 * progress)) / 255
    let colorProg = UIColor(red: redBlueValue, green: redBlueValue, blue: 1.0, alpha: 1.0)

    sendProgress.setTintColor(colorProg)
    sendProgress.setProgress(progress)
}

Upvotes: 0

Related Questions