SwiftUI add subview dynamically but the animation doesn't work

Related searches

I would like to create a view in SwiftUI that add a subview dynamically and with animation.

struct ContentView : View {
    @State private var isButtonVisible = false

    var body: some View {
        VStack {
            Toggle(isOn: $isButtonVisible.animation()) {
                Text("add view button")
            }

           if isButtonVisible {
                 AnyView(DetailView())
                      .transition(.move(edge: .trailing))
                      .animation(Animation.linear(duration: 2))
             }else{
                    AnyView(Text("test"))
            }
        }
    }
}

The above code works fine with the animation . however when i move the view selection part into a function, the animation is not working anymore (since i want to add different views dynamically, therefore, I put the logic in a function.)

struct ContentView : View {
    @State private var isButtonVisible = false
    var body: some View {
        VStack {
            Toggle(isOn: $isButtonVisible.animation()) {
                Text("add view button")
            }

            subView().transition(.move(edge: .trailing))
                     .animation(Animation.linear(duration: 2))   
    }

     func subView() -> some View {
         if isButtonVisible {
             return AnyView(DetailView())
         }else{
            return AnyView(Text("test"))
        }
    }
}

it looks totally the same to me, however, i don't understand why they have different result. Could somebody explain me why? and any better solutions? thanks alot!

Here's your code, modified so that it works:

struct ContentView : View {
    @State private var isButtonVisible = false

    var body: some View {
        VStack {
            Toggle(isOn: $isButtonVisible.animation()) {
                Text("add view button")
            }

            subView()
                .transition(.move(edge: .trailing))
                .animation(Animation.linear(duration: 2))
        }
    }

    func subView() -> some View {
        Group {
            if isButtonVisible {
                DetailView()
            } else {
                Text("test")
            }
        }
    }
}

Note two things:

  1. Your two examples above are different, which is why you get different results. The first applies a transition and animation to a DetailView, then type-erases it with AnyView. The second type-erases a DetailView with AnyView, then applies a transition and animation.
  2. Rather that using AnyView and type-erasure, I prefer to encapsulate the conditional logic inside of a Group view. Then the type you return is Group, which will animate properly.
  3. If you wanted different animations on the two possibilities for your subview, you can now apply them directly to DetailView() or Text("test").

Update

The Group method will only work with if, elseif, and else statements. If you want to use a switch, you will have to wrap each branch in AnyView(). However, this breaks transitions/animations. Using switch and setting custom animations is currently not possible.

Fancy SwiftUI: Making an Interactive Overlay Control, But, it doesn't change the fact that I'm a huge fan of menus and controls over Maybe it's also because I'm so used to dynamically appearing menus and With the new declarative UI approach in SwiftUI, interactive overlay controls get Or perhaps used a spring animation instead of a linear on the Stack. A transition is an animation that occurs when you add or remove a view from the view hierarchy. Using an opacity transition fades the view in and out. But when the opacity reaches 0, the view is no longer there.

I was able to get it to work with a switch statement by wrapping the function that returns an AnyView in a VStack. I also had to give the AnyView an .id so SwiftUI can know when it changes. This is on Xcode 11.3 and iOS 13.3

struct EnumView: View {

    @ObservedObject var viewModel: ViewModel

    var body: some View {
        VStack {
            view(for: viewModel.viewState)
                .id(viewModel.viewState)
                .transition(.opacity)
        }
    }

    func view(for viewState: ViewModel.ViewState) -> AnyView {
        switch viewState {
        case .loading:
            return AnyView(LoadingStateView(viewModel: self.viewModel))
        case .dataLoaded:
            return AnyView(LoadedStateView(viewModel: self.viewModel))
        case let .error(error):
            return AnyView(ErrorView(error: error, viewModel: viewModel))
        }
    }

}

Also for my example in the ViewModel I need to wrap the viewState changes in a withAnimation block

withAnimation {
    self.viewState = .loading
}

Animating UIStackView subview layout, 100 Days of Swift 100 Days of SwiftUI Swift Knowledge Base SwiftUI by Example isHidden { UIView.animate(withDuration: 0.35) { [unowned self] in self. But with UIStackView it has a meaning, and that meaning is brilliant: the stack view The only vaguely interesting thing here is that we'll use Dynamic Type to make� SwiftUI has two ways for us to animate changes to its view hierarchy: animation() and withAnimation(). They are used in different places, but both have the effect of smoothing out changes to the views in our app. The animation() method is used on bindings, and it asks SwiftUI to animate any changes that result in the binding’s value being

In iOS 14 they added the possibility to use if let and switch statements in function builders. Maybe it helps for your issues:

https://www.hackingwithswift.com/articles/221/whats-new-in-swiftui-for-ios-14 (at the article's bottom)

How to add and remove views with a transition, SwiftUI uses a fade animation to insert or remove views, but you can There's also the .slide transition, which causes a view to be animated� I'm new to SwiftUI and Swift in general. I'm trying to make a reusable subview of a button that will send me to another View. Right now I have it hardcoded to send me to the RegisterScreen view. Is there a way to pass in a reference to a view and have the button send me to the view I pass in? This is the code for my subview:

Creating Simple View Animations in Swift, Not only do animations add to the user experience of the app, but The above looks more interesting than a static presentation, but the views getting animated at the same time, doesn't create that great an effect. addSubview(button) You will learn the basics of SwiftUI and start building a simple UI with� SwiftUI gives us a TabView for just this purpose, and it works much like a UITabBarController. Press Cmd+N to create a new SwiftUI View, calling it “AppView”. Creating tabs is as easy as putting different views inside an instance of TabView , but in order to add an image and text to the tab bar item of each view we need to use the tabItem

HeroTransitions/Hero: Elegant transition library for iOS & tvOS, Hero can also construct animations for unmatched views. By default, Hero provides dynamic duration based on the Material Design Motion Guide. and size—saving you the hassle, while providing consistent and delightful animations . Hero doesn't make any assumptions about how the view is built or structured. It won't� As Jacob mentioned earlier, you should never hesitate to re-factor your SwiftUI code because extracting a subview has virtually no runtime overhead. A view in SwiftUI and a view in a traditional UI framework fulfill the same primary role: they define a piece of UI. The view protocol only requires a single property: body. Which is itself a view.

SwiftUIPager: Basics. SwiftUIPager comes with a component called Pager.This component is built on SwiftUI native components — that is, it doesn’t depend on UIKit at all. This might not seem

Comments
  • Thank you so much for your help. You help me a lot. I get another problem. I could not set a switch inside the group. I will get the error "Closure containing control flow statement cannot be used with function builder 'ViewBuilder'" func subView() -> some View { Group { switch status { case .start: Text("start") break case .main: Text("main") break case .unknown: Text("unknown") break } } }
  • @justicepenny See my update. Basically, you can't, if you want to keep your animations. Use elseif statements, and submit feedback to Apple if you would like to use switch here.
  • yea, I have to use if else statement. and the enum has to be with raw value. anyway Thanks a lot for your help