2

I am developing an app with SwiftUI.

I have a NavigationView and I have buttons on the navigation bar. I want to replace the current view (which is a result of a TabView selection) with another one.

Basically, when the user clicks "Edit" button, I want to replace the view with another view to make the edition and when the user is done, the previous view is restored by clicking on a "Done" button.

I could just use a variable to dynamically choose which view is displayed on the current tab view, but I feel like this isn't the "right way to do" in SwiftUI. And this way I could not apply any transition visual effect.

Some code samples to explain what I am looking for.

private extension ContentView {
    @ViewBuilder
    var navigationBarLeadingItems: some View {
        if tabSelection == 3 {
            Button(action: {
                print("Edit pressed")
                // Here I want to replace the tabSelection 3 view by another view temporarly and update the navigation bar items
                }) {
                    Text("Edit")
            }
        }
    }
}

struct ContentView: View {    

    var body: some View {
        NavigationView {
            TabView(selection: $tabSelection) {
                ContactPage()
                    .tabItem {
                        Text("1")
                    }
                    .tag(1)
                Text("Chats")
                    .tabItem() {
                        Text("2")
                    }
                    .tag(2)
                SettingsView()
                    .tabItem {
                        Text("3")
                    }
                    .tag(3)
            }.navigationBarItems(leading: navigationBarLeadingItems)
        }
    }
}

Thank you

EDIT

I have a working version where I simply update a toggle variable in my button action that makes my view display one or another thing, it is working but I cannot apply any animation effect on it, and it doesn't look "right" in SwiftUI, I guess there is something better that I do not know.

pawello2222
  • 46,897
  • 22
  • 145
  • 209
BountyHunter
  • 85
  • 2
  • 7

1 Answers1

3

If you just want to add animations you can try:

struct ContentView: View {
    ...
    @State var showEditView = false

    var body: some View {
        NavigationView {
            TabView(selection: $tabSelection) {
                ...
                view3
                    .tabItem {
                        Text("3")
                    }
                    .tag(3)
            }
            .navigationBarItems(leading: navigationBarLeadingItems)
        }
    }
}
private extension ContentView {
    var view3: some View {
        VStack {
            if showEditView {
                FormView()
                    .background(Color.red)
                    .transition(.slide)
            } else {
                Text("View 3")
                    .background(Color.blue)
                    .transition(.slide)
            }
        }
    }
}

struct FormView: View {
    var body: some View {
        Form {
            Text("test")
        }
    }
}

A possible alternative is to use a ViewRouter: How To Navigate Between Views In SwiftUI By Using An @EnvironmentObject.

pawello2222
  • 46,897
  • 22
  • 145
  • 209
  • Thank you. I tried applying the .transition(.slide) to a Form { } bloc which is displayed only if showEditView is true, but it doesn't seem to work. There is no animation effect. I tried applying the .transition to each subitem of the Form but the result is the same. – BountyHunter Aug 12 '20 at 21:04
  • @BountyHunter I updated my code with displaying a new Form. I can see the transition animations (Xcode 11.6, iOS 13.6). – pawello2222 Aug 12 '20 at 21:07
  • 1
    You may also need to add .animation(.default) to the section you want to animate (in this case TabView or NavigationView) – TheLivingForce Aug 12 '20 at 21:11
  • ```var settingsview: some View { VStack { DisplayProfile(contact: self_info) .padding(.top) Spacer() if settingsEdit { Text("Hello1").transition(.slide) } else { Text("Hello2").transition(.slide) } } } ``` I set up everything as you did, but here is a strange behavior : When I do not click on "Edit" : https://i.imgur.com/0WcY8ZM.png (this is normal) But when I click : https://i.imgur.com/fXcsmbw.png (also there is no transition animation) – BountyHunter Aug 12 '20 at 21:19
  • Sorry for my last comment which is not well formatted but I could not format my code here in comment section. – BountyHunter Aug 12 '20 at 21:21
  • @BountyHunter Try copying my code to the playground and replacing parts one by one adapting to your needs. Or follow the link I gave you in my answer. – pawello2222 Aug 12 '20 at 21:23
  • The .animation(.default) as suggested by @TheLivingForce was indeed necessary, after adding it to my NavigationView the animations are working now. Your code is also working pawello2222 but mine is not. I will try to figure out what's missing but since your solution is working and I didn't know how to use this animation method, your solution is valid, thank you! – BountyHunter Aug 12 '20 at 21:34
  • @BountyHunter You're welcome :) `.animation(.default)` may be just another SwiftUI bug... – pawello2222 Aug 12 '20 at 21:37
  • 1
    Update: I got it working, it is not perfect but that will do for now. The problem on my screenshots above was because I used the .transition(.slide) without .animation(.default) which made the text to duplicate without finishing the animation... – BountyHunter Aug 12 '20 at 21:43