Kishan Seksaria
Kishan Seksaria

Reputation: 1

How to animate this in SwiftUI?

I am new to iOS development and I have been working on a project using SwiftUI. I have a sheet where I can buy or sell some stocks. On successful transaction, I am supposed to show a green screen with success message. The problem is that my implementation just shows the green screen suddenly as opposed to it being animated/faded in. Here is what I mean: This is the way my app behaves and this is how I want it to behave.

Here is the code for the sheet:

//
//  TradingSheetView.swift
//  Stock Search
//
//  Created by Kishan  on 4/29/24.
//

import SwiftUI
import SimpleToast

struct TradingSheetView: View {
    
    @EnvironmentObject var root: ToastViewModel
    @StateObject var viewModel = TradingSheetViewModel()
    
    @Binding var isTrading: Bool
    @Binding var company: Company?
    @Binding var portfolio: Portfolio?
    @Binding var wallet: Wallet?
    
    private var tradingQuantity: Int {
        let tradingQuantityInt = Int(viewModel.tradingQuantity)
        //      if tradingQuantityInt == nil {
        //          root.showToast(saying: "Please enter a valid amount")
        //      }
        return tradingQuantityInt ?? 0
    }
    
    private var tradingAmount: Double {
        return (viewModel.quote?.c ?? 0) * Double(tradingQuantity)
    }
    
    var body: some View {
        ZStack {
            VStack {
                HStack {
                    Spacer()
                    Button {
                        isTrading.toggle()
                    } label: {
                        Image(systemName: "xmark")
                            .foregroundStyle(Color(.label))
                    }
                }
                
                Text("Trade \(company?.name ?? "") shares")
                    .bold()
                
                Spacer()
                
                HStack {
                    TextField("0",
                                        text: $viewModel.tradingQuantity)
                    .font(.system(size: 100, weight: .light))
                    .keyboardType(.numberPad)
                    
                    Text(tradingQuantity > 1 ? "Shares" : "Share")
                        .font(.largeTitle)
                        .offset(y: 20)
                }
                
                HStack {
                    Spacer()
                    
                    Text("x $\((viewModel.quote?.c ?? 0).getTwoPointsString())/share = $\(tradingAmount.getTwoPointsString())")
                }
                
                Spacer()
                
                Text("$\((wallet?.amount ?? 0).getTwoPointsString()) available to buy \(company?.ticker ?? "")")
                    .font(.caption)
                    .foregroundStyle(.secondary)
                    .padding()
                
                HStack(spacing: 20) {
                    Button {
                        Task {
                            if tradingAmount > (wallet?.amount ?? 0) {
                                root.showToast(saying: "Not enough money to buy")
                                return
                            }
                            if tradingQuantity <= 0 {
                                root.showToast(saying: "Cannot buy non-positive shares")
                                return
                            }
                            await viewModel.buy(tradingQuantity,
                                                                    of: company?.ticker,
                                                                    at: viewModel.quote?.c,
                                                                    called: company?.name)
                        }
                    } label: {
                        PortfolioDetailsButton(title: "Buy")
                    }
                    Button {
                        Task {
                            if tradingQuantity > (portfolio?.quantity ?? 0) {
                                root.showToast(saying: "Not enough shares to sell")
                                return
                            }
                            if tradingQuantity <= 0 {
                                root.showToast(saying: "Cannot sell non-positive shares")
                                return
                            }
                            await viewModel.sell(tradingQuantity,
                                                                     of: company?.ticker,
                                                                     at: viewModel.quote?.c)
                        }
                    } label: {
                        PortfolioDetailsButton(title: "Sell")
                    }
                }
            }
            .padding()
            .onAppear() {
                Task {
                    await viewModel.fetchCurrentQuote(for: company?.ticker ?? "")
                }
            }
            
            if viewModel.transactionSuccess {
                withAnimation(.easeInOut.speed(5)) {
                    ZStack {
                        Color.green.ignoresSafeArea()
                        
                        VStack() {
                            Spacer()
                            
                            Text("Congratulations!")
                                .bold()
                                .font(.largeTitle)
                                .foregroundStyle(.white)
                            
                            Text(viewModel.transactionMessage)
                                .font(.callout)
                                .foregroundStyle(.white)
                                .padding(.vertical, 1)
                            
                            Spacer()
                            
                            Button {
                                isTrading.toggle()
                            } label: {
                                Text("Done")
                                    .bold()
                                    .frame(width: 350, height: 50)
                                    .background(in: .capsule)
                                    .foregroundStyle(.green)
                            }
                        }
                        .padding()
                    }
                }
            }
        }
        .simpleToast(isPresented: $root.isToastVisible,
                 options: root.toastOptions) {
            ToastView(message: $root.toastMessage)
        }
    }
}

#Preview {
    TradingSheetView(isTrading: .constant(true),
                                     company: .constant(mockCompany),
                                     portfolio: .constant(mockPortfolio),
                                     wallet: .constant(mockWallet))
}

Edit: As stated by @Sweeper below, I tried to replicate the view. I am not sure if it replicates it completely but here is the code:

//
//  TestView.swift
//  Stock Search
//
//  Created by Kishan  on 4/29/24.
//

import SwiftUI

struct TestView: View {
    
    @State var success = false
    
    var body: some View {
        ZStack {
            
            Button("Press here to perform transaction") {
                Task {
                    await performTransaction()
                }
            }
            
            if success {
                ZStack {
                    Color.green.ignoresSafeArea()
                    
                    VStack {
                        Text("Congratulations!")
                            .bold()
                            .font(.title)
                            .foregroundStyle(.white)
                            .padding(.vertical)
                        
                        Button {
                            Task {
                                await performTransaction()
                            }
                        } label: {
                            Text("Done")
                                .bold()
                                .frame(width: 300, height: 50)
                                .background(in: .capsule)
                                .foregroundStyle(.green)
                        }
                    }
                }
            }
        }
    }
    
    func performTransaction() async {
        // Perform some transaction
        success.toggle()
    }
}

#Preview {
    TestView()
}

I have tried using the .animation modifier and withAnimation as well, but it does not seem to work. Is there something that might be conflicting with how the animations are supposed to be performed?

Upvotes: 0

Views: 142

Answers (1)

user24065788
user24065788

Reputation:

func performTransaction() async {
    // Perform some transaction
    withAnimation(.easeIn.speed(0.6)) {
        success.toggle()
    }
}

Read more about animation https://www.hackingwithswift.com/quick-start/swiftui, scroll down to Animation

Upvotes: 0

Related Questions