视图上的动画背景渐变

问题描述 投票:0回答:2

试图用动画背景渐变来愚弄。当切换动画时,它会改变结束半径。 每当我合并移动整个 VStack 的动画(下面的 gif)时,它就会产生奇怪的行为。

我尝试将堆栈放入 ZStack 中,认为这将是一个解决方案,但最终结果仍然相同。

enter image description here

好奇到底是什么导致了这种行为

struct LandingPage: View {
    @AppStorage("signedIn") var signedIn = false
    @Environment (\.dismiss) var dismiss
    
    @StateObject var vm = DashboardLogic()
    
    @State private var animateGradient = false

    
    @ViewBuilder
    var body: some View {
        if(signedIn){
           // Text("Random Page")
        }
        else{
            NavigationView{
                VStack{
                        Image("bodybuilding-1") // << main image
                            .resizable()
                            .scaledToFit()
                            .frame(width:150, height:150)
                            //.renderingMode(.template)
                            .foregroundColor(.black)
                            .padding(.top, 200)
                    
                        Text("Welcome to Meal Journal")
                            .font(.title)
                            .padding()
                    
                    .offset(y:-25) // << adjusts title
                    
                    VStack{
                        NavigationLink(destination:dummyPage() .navigationBarHidden(true),
                       label:{
                            Text("Get Started").fontWeight(.bold)
                                .frame(minWidth: 0, maxWidth: 200)
                                .padding(10)
                                .foregroundColor(.white)
                            //draw rectange around buttons
                                .background(
                                    RoundedRectangle(cornerRadius: 20)
                                        .fill(
                                            LinearGradient(
                                                colors: [.orange, .yellow],
                                                startPoint: .topLeading,
                                                endPoint: .bottomTrailing
                                            )))
                                        })
                        
                        NavigationLink(destination: DummyPage().navigationBarHidden(true), label: {
                            Text("Login").fontWeight(.semibold)
                                .frame(minWidth:0, maxWidth: 200)
                                .padding(10)
                                .foregroundColor(.black)
                                .overlay( RoundedRectangle(cornerRadius: 25)
                                            .stroke(Color.gray, lineWidth: 3)
                                    )
                        })
                            .padding()
                    }
                    Rectangle()
                        .frame(height: 0)
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                        .ignoresSafeArea()
                }
                //.background(Color.purple)
                .background(RadialGradient(gradient: Gradient(colors: [.yellow, .green]), center: .center, startRadius: 312, endRadius: animateGradient ? 100 : 450))
                 .onAppear {
                DispatchQueue.main.async {  
                    withAnimation(.linear(duration: 2.0).repeatForever(autoreverses: true)) {
                        animateGradient.toggle()
                    }
                }
            }
                
            }
            
        }
    }
}
swift swiftui
2个回答
3
投票

我没有仔细检查你的整个代码,但可能有帮助的一件事是记住背景是它自己的视图,所以你可以(并且经常必须)将修饰符应用于背景视图本身。因此,不要将父视图上的

.onAppear
添加到背景视图中,即:

var backgroundView: some View {
        
    RadialGradient(gradient: Gradient(colors: [.yellow, .green]), center: .center, startRadius: 312, endRadius: animateGradient ? 100 : 450)
        .onAppear {
            withAnimation(.linear(duration: 2.0).repeatForever(autoreverses: true)) {
                animateGradient.toggle()
            }
        }
    }
}

然后父视图简单地使用背景视图:

VStack {
    Image("bodybuilding-1")
    ...
}
.background(backgroundView)

游乐场示例:

struct AnimatedBackgroundView: View {
    
    @State private var animateGradient = false
    
    @State var scale = 1.0

    var body: some View {
        
        VStack {
            Text("Hello")
            Button("Do it", action: {})
        }
        .frame(
            maxWidth: .infinity,
            maxHeight: .infinity
        )
        .scaleEffect(scale)
        .background(backgroundView)
     }
    
    var backgroundView: some View {
        
        RadialGradient(gradient: Gradient(colors: [.yellow, .green]), center: .center, startRadius: 312, endRadius: animateGradient ? 100 : 450)
            .onAppear {
                withAnimation(.linear(duration: 2.0).repeatForever(autoreverses: true)) {
                    animateGradient.toggle()
                }
        }
    }
}

struct ContentView: View {

    var body: some View {
        
        AnimatedBackgroundView()
            .frame(
                width: 500,
                height: 600
            )
     }
}
    
PlaygroundPage.current.setLiveView(ContentView())

但就像我说的:我没有调查你的整个代码,所以也许其他一些问题会阻止它工作


0
投票

您应该将动画设置为任务 {} 而不是 onAppear。使用此动画也可以代替整个视图。

@State var animateGradient = false

LinearGradient(colors: [.purple, .yellow], startPoint: animateGradient ? .topTrailing : .bottomTrailing, endPoint: animateGradient ? .bottomLeading : .topTrailing)
        .ignoresSafeArea()
        .frame(width: 200, height: 200)
        .task {
            withAnimation(.linear(duration: 5.0).repeatForever(autoreverses: true)) {
                animateGradient.toggle()
            }
        }
© www.soinside.com 2019 - 2024. All rights reserved.