0

I have a view that looks like this: enter image description here

I would like to animate the gradient in the listRowBackground, but I am not able to for some reason. Here is the code I have:

import SwiftUI

struct SnakeColorView: View {
    @AppStorage("HeadColor") private var HeadColor : Color = .white
    @AppStorage("BodyColor") private var BodyColor : Color = .white
    
    @State private var animateGradient : Bool = false
    
    var body: some View {
        let bgGradient = LinearGradient(colors: [Color("Bi Pink"), Color("Bi Purple"), Color("Bi Blue")], startPoint: animateGradient ? .top : .bottom, endPoint: animateGradient ? .bottom : .top)
        
        List {
            ColorPicker("Set the color of the Snake's head!!", selection: $HeadColor)
            ColorPicker("Set the color of the Snake's body!!", selection: $BodyColor)
            HStack{
                Spacer()
                VStack(spacing: 0) {
                    ZStack{
                        Ellipse()
                            .fill(HeadColor)
                        Ellipse()
                            .strokeBorder(.white, lineWidth: 3.2)
                        
                    }.frame(width: 100, height: 175)
                    ForEach(0..<7) { _ in
                        ZStack {
                            Circle()
                                .fill(BodyColor)
                            Circle()
                                .strokeBorder(.white, lineWidth: 3.2)
                        }
                    }.frame(width: 50, height: 50)
                }
                Spacer()
            }
            .listRowBackground(bgGradient)
            .ignoresSafeArea()
            .onAppear {
                withAnimation(.linear(duration: 2.0).repeatForever(autoreverses: true)) {
                    animateGradient.toggle()
                }
            }
        }
    }
}

I have the state variable for the animation, and it should be triggered by onAppear but nothing happens.

1 Answers1

0

Add .animation property with value to explicitly telling LinearGradient what animation to use when animateGradient value changes. The following code with output:

Code:

@State private var animateGradient : Bool = false
    
    var body: some View {
        let bgGradient = LinearGradient(colors: [Color.pink, Color.purple, Color.blue], startPoint: animateGradient ? .topLeading : .bottomTrailing, endPoint: animateGradient ? .bottomTrailing : .topLeading)
        
        List {
            HStack{
                Spacer()
                VStack(spacing: 0) {
                    ZStack{
                        Ellipse()
                            .fill(Color.red)
                        Ellipse()
                            .strokeBorder(.white, lineWidth: 3.2)
                        
                    }.frame(width: 100, height: 175)
                    ForEach(0..<7) { _ in
                        ZStack {
                            Circle()
                                .fill(Color.yellow)
                            Circle()
                                .strokeBorder(.white, lineWidth: 3.2)
                        }
                    }.frame(width: 50, height: 50)
                }
                Spacer()
            }
            .listRowBackground(
                bgGradient
                    .animation(.linear(duration: 5.0).repeatForever(autoreverses: true), value: animateGradient) // ---> add animation

            )
            .ignoresSafeArea()
            .onAppear {
                animateGradient.toggle() // --> toggle value
                
            }
        }
    }

Output:

enter image description here

Kishan Bhatiya
  • 2,175
  • 8
  • 14