Pradeep Chakravarti
Pradeep Chakravarti

Reputation: 33

How do I animate the color and width of a view?

I have a progress bar that I have written like such.

ZStack(alignment: .leading) {
                RoundedRectangle(cornerRadius: 20)
                    .foregroundColor(.gray)
                    .frame(width: 300, height: 20, alignment: .center)
                RoundedRectangle(cornerRadius: 20)
                    .foregroundColor(Color(red: min(2.0 - (fraction * 2.0), 1.0), green: min((fraction * 2.0), 1.0), blue: 0))
                    .frame(width: 300 * fraction, height: 20)
                    
            }

The progress is represented as a decimal in the variable fraction. Essentially a gray bar is the total progress and the progress is represented by a smaller bar whose width and color depend on the fraction.

Here is an example of this code with fraction set to increasing amounts: progress bar

When the view is first loaded, I would like for all the bars to start at fraction = 0 and red and quickly expand and color to their desired fraction over the course of one second.

My problem is I have not figured out how to animate a variable's value and also use it in a modifier. This while redrawing the view.

Something like this is ideal(though this code obviously does not compile):


                RoundedRectangle(cornerRadius: 20)
                    .foregroundColor(Color(red: min(2.0 - ((fraction*frame) * 2.0), 1.0), green: min(((fraction*frame) * 2.0), 1.0), blue: 0))
                    .frame(width: 300 * (fraction*frame), height: 20)
                    .animate(start: frame = 0; increment: frame += 0.1; end: frame <= 1, duration: 1s)

Upvotes: 2

Views: 68

Answers (1)

Asperi
Asperi

Reputation: 257593

It is possible to do having each of progress view separate with own progress state that track changed value.

Tested with Xcode 13.4 / iOS 15.5

demo

Main part:

        ZStack(alignment: .leading) {
            RoundedRectangle(cornerRadius: 20)
                .foregroundColor(.gray)
                .frame(width: 300, height: 20, alignment: .center)
            RoundedRectangle(cornerRadius: 20)
                .foregroundColor(Color(red: min(2.0 - (fraction * 2.0), 1.0), green: min((fraction * 2.0), 1.0), blue: 0))
                .frame(width: 300 * fraction, height: 20)
        }
        .animation(.easeInOut(duration: 1.0), value: fraction)
        .onAppear {
            fraction = currentProgress
        }
        .onChange(of: currentProgress) {
            fraction = $0
        }

Test module on GitHub

Upvotes: 3

Related Questions