1

I have tried to use Buttons and Navigation Links from various examples when researched on this channel and on the net. The NavigationLink would be ok, except that the NavigationView is pushing everything down in my view.

I have a view that contains an image and a text like this: ( x Close) but when I use the code below, the Close button is not doing anything.

In ContentView() I have a (?) button that takes me from WalkthroughView(), then to the PageTabView, then to this view, TabDetailsView:

ContentView():

ZStack {
        NavigationView {
            VStack {
                Text("Hello World")
                    .padding()
                    .font(.title)
                    .background(Color.red)
                    .foregroundColor(.white)
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button {
                        withAnimation {
                            showOnBoarding = true
                        }
                    } label: {
                        Image(systemName: "questionmark.circle.fill")
                    }
                }
            }
        }
        .accentColor(.red)
        .disabled(showOnBoarding)
        .blur(radius: showOnBoarding ? 3.0 : 0)
        
        if showOnBoarding {
            WalkthroughView(isWalkthroughViewShowing: $isWalkthroughViewShowing)
        }
    }
    .onAppear {
        if !isWalkthroughViewShowing {
            DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                withAnimation {
                    showOnBoarding.toggle()
                    isWalkthroughViewShowing = true
                }
            }
        }
    }

WalkthroughView():

var body: some View {
    ZStack {
        GradientView()
        VStack {
            PageTabView(selection: $selection)

            // shows Previous/Next buttons only
            ButtonsView(selection: $selection) 
        }
    }
    .transition(.move(edge: .bottom))
}

PageTabView():

var body: some View {
    TabView(selection: $selection) {
        ForEach(tabs.indices, id: \.self) { index in
            TabDetailsView(index: index)
        }
    }
    .tabViewStyle(PageTabViewStyle())
}

below, is the TabDetailsView():

At the top of the view is this Close button, when pressed, should send me back to ContentView, but nothing is happening.

struct TabDetailsView: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    let index: Int

then, inside the body:

VStack(alignment: .leading) {
        Spacer()
        VStack(alignment: .leading) {
            // Button to close each walkthrough page...
            Button(action: {
                self.presentationMode.wrappedValue.dismiss()
            }) {
                Image(systemName: "xmark.circle.fill")
                Text("Close")
            }
            .padding(.leading)
            .font(.title2)
            .accentColor(.orange)

            Spacer()
            VStack {
                Spacer()
                Image(tabs[index].image)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 415)
                    .padding(.leading, 10)
                
                Text(tabs[index].title)
                    .font(.title)
                    .bold()
                
                Text(tabs[index].text)
                    .padding()
                Spacer()
            }
            .foregroundColor(.white)
        }
    }
halfer
  • 19,824
  • 17
  • 99
  • 186
LizG
  • 2,246
  • 1
  • 23
  • 38

1 Answers1

1
    if showOnBoarding {
        WalkthroughView(isWalkthroughViewShowing: $isWalkthroughViewShowing)
    }

Inserting view like above is not a presentation in standard meaning, that's why provided code does not work.

As this view is shown via showOnBoarding it should be hidden also via showOnBoarding, thus the solution is to pass binding to this state into view where it will be toggled back.

Due to deep hierarchy the most appropriate way is to use custom environment value. For simplicity let's use ResetDefault from https://stackoverflow.com/a/61847419/12299030 (you can rename it in your code)

So required modifications:

    if showOnBoarding {
        WalkthroughView(isWalkthroughViewShowing: $isWalkthroughViewShowing)
          .environment(\.resetDefault, $showOnBoarding)
    }

and in child view

struct TabDetailsView: View {
    @Environment(\.resetDefault) var showOnBoarding

    // .. other code

            Button(action: {
                self.showOnBoarding.wrappedValue.toggle() 
            }) {
                Image(systemName: "xmark.circle.fill")
                Text("Close")
            }
Asperi
  • 228,894
  • 20
  • 464
  • 690