1

I created this custom progress view with bars for the progress, how can I animate the the green color in the next bar when it's time to go to the next element? I am looking for it to fill the bar slowly from left to right

struct ContentView: View {
    var body: some View {
        ProgressBar(lastIndex: 8, currentIndex: 4)
            .padding(.horizontal, 23)
            .padding(.top, 10)
        Spacer()
    }
}

struct ProgressBar: View {
    var lastIndex: Int
    var currentIndex: Int

    var body: some View {
        HStack(alignment: .center, spacing: 4) {
            ForEach(0...lastIndex, id: \.self) { i in
                BarElement(selected: i <= currentIndex)
            }
        }
    }
}

struct BarElement: View {
    var selected: Bool

    var body: some View {
        Capsule()
            .fill(selected ? .green : Color(UIColor.lightGray))
            .frame(width: 33, height: 5, alignment: .center)
    }
}

enter image description here

tHatpart
  • 1,302
  • 3
  • 12
  • 27

1 Answers1

1

It's hard to answer without code but if you have all separated rectangles, it should be enough using .animation(.linear) on all the rectagles, so when the values changes it should animated as you asked.

This will do what you wanted.

struct BarElement: View {
    var value : CGFloat = 0.0
    var selected: Bool
    

    var body: some View {
        ZStack (alignment: .leading){
            Capsule()
                .fill(Color(UIColor.lightGray))
                .frame(width: 33, height: 5, alignment: .leading)
                .animation(.linear, value: selected)
        Capsule()
            .fill(.green)
            .frame(width: selected ? 33 : 0, height: 5, alignment: .leading)
            .animation(.linear, value: selected)
        }
    }
}

Eddo10957
  • 25
  • 7
  • Just posted the code, can't believe I forgot to include that, you can copy and paste it into a project to replicate – tHatpart Jun 03 '22 at 14:09
  • Ok so you can use the .animation(.linear, value: selected) in the Capsule code. It won't fill left to right but it will fill smoothly. If you want left to right to be achieved, you should use in the Bar Element A Zstack where you put the gray capsule on top and the green capsule down in the code. By passing to the BarElement the value of progress, like 0 to 1, and with the .animation(..), it will fill left to right. – Eddo10957 Jun 03 '22 at 14:25
  • `struct BarElement: View { var value : CGFloat = 0.0 var selected: Bool var body: some View { ZStack (alignment: .leading){ Capsule() .fill(Color(UIColor.lightGray)) .frame(width: 33, height: 5, alignment: .leading) .animation(.linear, value: selected) Capsule() .fill(.green) .frame(width: selected ? 33 : 0, height: 5, alignment: .leading) .animation(.linear, value: selected) } } } ` This will do the magic, sorry for poor indentation – Eddo10957 Jun 03 '22 at 14:31
  • it is not animating for me – tHatpart Jun 03 '22 at 16:18
  • what is ```value``` for? it was never used – tHatpart Jun 03 '22 at 16:19
  • Sorry value was a try you are right in the end I didn't use it. Anyway was animating for me. Don't know if you have any other problem in the code maybe. – Eddo10957 Jun 03 '22 at 17:07
  • This was the content I used to try. `struct ContentView: View { @State var current = 4 var body: some View { ProgressBar(lastIndex: 8, currentIndex: current) .padding(.horizontal, 23) .padding(.top, 10) Spacer() Button("add"){ current+=1 } } }` – Eddo10957 Jun 03 '22 at 17:09