UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: Gradient animation inside of Navigation View

Forums > SwiftUI

Hi all. I was attempting to animate a LinearGradient view inside of a NavigationView, but unexpected behavior occured. Instead of the color animation that would occur if the LinearGradient was not wrapped inside the NavigationView, the LinearGradient view grows and shrinks along with the color change. I discovered on stack overflow that you can wrap the "withAnimation" call inside of a Dispatch.main.async closure to resolve the issue. Does anyone understand why this resolves the issue? Example below. This works as expected (the color swaps from teal to blue vertically on a loop):

NavigationView{
            ZStack{
                LinearGradient(gradient: Gradient(colors:[.teal, .blue]), startPoint: isAnimating ? .topLeading : .bottomLeading, endPoint: .bottomLeading)
                    .ignoresSafeArea()
                    .onAppear() {
                        DispatchQueue.main.async{
                            withAnimation(.linear(duration: 20).repeatForever(autoreverses: true)){
                                isAnimating.toggle()
                            }
                        }
                     }
             }
  }

This doesn't work (instead the LinearGradient view grows and shrinks continuosly):

NavigationView{
            ZStack{
                LinearGradient(gradient: Gradient(colors:[.teal, .blue]), startPoint: isAnimating ? .topLeading : .bottomLeading, endPoint: .bottomLeading)
                    .ignoresSafeArea()
                    .onAppear() {
                            withAnimation(.linear(duration: 20).repeatForever(autoreverses: true)){
                                isAnimating.toggle()
                            }
                     }
             }
  }

1      

Your bio says you served in the Navy? Thank you for your service to the Crown!

Did you try NOT using a withAnimation() block?

//  GradientAnimationView.swift
//  Created by Obelix on 3/13/22.
//
import SwiftUI
// Please don't name this "ContentView"
struct GradientAnimationView: View {
    @State private var isAnimating = false

    let startGradient = Gradient(colors: [.blue, .yellow]) // Very popular these days

    var body: some View {
        NavigationView {
            ZStack{
                LinearGradient(gradient: startGradient,
                               startPoint: isAnimating ? .topLeading : .bottomLeading,
                               endPoint: .bottomLeading)
                    .animation(.linear(duration: 5).repeatForever(autoreverses: true),
                               value: isAnimating)
            }
        }
        .onAppear { isAnimating.toggle() }  // light the fuze
    }
}

In this code snip, you're explicitly telling the LinearGradient what animation to use whenever the value isAnimating changes.

2      

Thanks @Obelix - that did the trick. U.S. Navy - not the Queen's navy, but we are definitely on the same side! Good point on the gradient colors as well - that's a must.

1      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.