There are 2 pages in the demo
- main view with a navigation button to the the content view
- content view has a image overlaying a border animation.
the problem is if it starts from launching app, then clicking the button, then it's weird of the animation part however, if it's already launched, e.g. back to main page from content view, then go to content view again, the behavior is as expectation also, i tested, if remove the main view and directly launch from the content view, the behavior is good.
So i guess there's magic in navigationstack break something. What's the reason and how to fix it?
here's the code and screen record
import SwiftUI
@main
struct TestSwiftuiApp: App {
@StateObject var navManager = NavManager()
var body: some Scene {
WindowGroup {
MainView()
.environmentObject(navManager)
}
}
}
struct MainView: View {
@EnvironmentObject var navManager: NavManager
var body: some View {
NavigationStack(path: $navManager.path) {
ZStack {
VStack {
Button("click to new page") {
navManager.path.append("ContentView")
}
}
}
.navigationDestination(for: String.self) { destination in
let a = print("destination \(destination)")
if destination == "ContentView" {
ContentView()
}
}
}
}
}
class NavManager: ObservableObject {
@Published var path = NavigationPath()
public func backToMain() {
path.removeLast(path.count)
}
}
struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
.overlay(
CardGradient(gradient: Gradient(colors: [.red, .yellow, .blue]),
duration: 1)
)
}
}
}
struct CardGradient: View {
let gradient: Gradient
let width: CGFloat
let duration: Double
@State var animation = false
init(gradient: Gradient, width: CGFloat = 5, duration: Double = 2) {
self.gradient = gradient
self.width = width
self.duration = duration
}
var body: some View {
Rectangle()
.stroke(
LinearGradient(gradient: gradient,
startPoint: animation ? .topLeading : .bottomLeading,
endPoint: animation ? .bottomTrailing : .topTrailing),
lineWidth: width
)
.animation(.linear(duration: duration).repeatForever(), value: animation)
.border(.black, width: 3)
.onAppear {
animation = true
}
}
}