Max B
Max B

Reputation: 375

NavigationView scrolling broken when using TabView

With the below code I get a very weird scrolling behaviour in my TabViews, LoginView is called on app launch:

struct LoginView: View {
    @State private var presentContent = false
    
    var body: some View {
        
        
        return NavigationView {
            ZStack{
                NavigationLink(
                    destination: ContentView(),
                    isActive: $presentContent,
                    label: {
                        EmptyView()
                    })
                
                Button("TEst") {
                    self.presentContent.toggle()
                }
            }
            
        }
    }
}

struct ContentView: View {
    var body: some View {
        TabView{
            Group{
                List{
                    Text("Item 1")
                    Text("Item 2")
                    Text("Item 3")
                }
            }
            .navigationTitle("Transactions")
            .tabItem {
                Image(systemName: "list.dash")
                Text("Transactions")
            }
            Group{
                List{
                    Text("Item 11")
                    Text("Item 12")
                    Text("Item 13")
                }
            }
            .navigationTitle("Summary")
            .tabItem {
                Image(systemName: "list.dash")
                Text("Summary")
            }
        }
    }
}

enter image description here

Any ideas what that might cause?

Here the issue in verbatim: after tapping the button in the LoginView to jump over to the ContentView, I see the first tab. Now I scroll the list up and it goes beyond the screen border which is not correct.

UPDATE: Adding the app launch code below to emphasize the point "LoginView is called on app launch:":

struct TabTestApp: App {
    var body: some Scene {
        WindowGroup {
            LoginView()
        }
    }
}

Upvotes: 0

Views: 772

Answers (2)

cole
cole

Reputation: 1273

Use a NavigationView inside the TabView instead of Group. The login view you have isn't presented or even used. This will fix the scrolling issue.

Edit: Adding a login add additional elements which are unclear. You'd need a data model to handle the login details yourself, but a simple approach could be something like this.

class LoginModel: ObservableObject {
    @Published var loggedin: Bool = false
}

struct Login: View {
    @ObservedObject var model: LoginModel
    @Environment(\.dismiss) var dismiss
    var body: some View {
        NavigationView {
            List {
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button(action: {
                        dismiss()
                        print("if successful login handle here and dismiss")
                    }, label: {
                        Label("Close", systemImage: "xmark")
                            .labelStyle(.iconOnly)
                    })
                }
            }
        }
    }
}

struct ContentView: View {
    @StateObject var loginmodel =  LoginModel()
    @State var sheet: Bool = false
    
    var body: some View {
        TabView {
            NavigationView {
                VStack {
                    if !loginmodel.loggedin {
                        Button(action: {
                            sheet.toggle()
                        }, label: {
                            Label("Login", systemImage: "person.circle.fill")
                        })
                    } else {
                        List {
                            NavigationLink("Item 1", destination: Text("Item 1"))
                            NavigationLink("Item 2", destination: Text("Item 2"))
                            NavigationLink(destination: Text("Item 3")) {
                                Text("Item 3")
                            }
                        }
                    }
                }
                .navigationTitle("Transactions")
            }
            .sheet(isPresented: $sheet) {
                Login(model: loginmodel)
            }
            .tabItem {
                Label("Transactions", systemImage: "list.dash")
            }
            
            NavigationView {
                List {
                    Text("Item 11")
                    Text("Item 12")
                    Text("Item 13")
                }
                .navigationTitle("Summary")
            }
            .tabItem {
                Label("Summary", systemImage: "chart.line.uptrend.xyaxis")
            }
        }
    }
}
struct ContentView: View {
    var body: some View {
        TabView {
            NavigationView {
                List {
                    // Either or navigation link if needed
                    NavigationLink("Item 1", destination: Text("Item 1"))
                    NavigationLink("Item 2", destination: Text("Item 2"))
                    NavigationLink(destination: Text("Item 3")) {
                        Text("Item 3")
                    }
                }
                .navigationTitle("Transactions")
            }
            .tabItem {
                Label("Transactions", systemImage: "list.dash")
            }
            
            NavigationView {
                List {
                    Text("Item 11")
                    Text("Item 12")
                    Text("Item 13")
                }
                .navigationTitle("Summary")
            }
            .tabItem {
                Label("Summary", systemImage: "chart.line.uptrend.xyaxis")
            }
        }
    }
}

example

Upvotes: 1

Max B
Max B

Reputation: 375

Ok, I have changed the whole code to

//
//  ContentView.swift
//  TabTest
//
//  Created by Max on 2022-05-04.
//

import SwiftUI

struct LoginView: View {
    @Environment(\.presentationMode) var presentationMode
    @State private var presentContent = false
    
    var body: some View {
        return NavigationView {
            ZStack{
                Button("Login") {
                    presentationMode.wrappedValue.dismiss()
                }
            }
        }
    }
}

struct ContentView: View {
    @State private var isPresented = false
    
    
    var body: some View {
        TabView{
            NavigationView{
                List{
                    Text("Item 1")
                    Text("Item 2")
                    Text("Item 3")
                }
                .navigationTitle("Transactions")
                .navigationBarBackButtonHidden(true)
            }
            .tabItem {
                Image(systemName: "list.dash")
                Text("Transactions")
            }
            
            NavigationView{
                List{
                    Text("Item 11")
                    Text("Item 12")
                    Text("Item 13")
                }
                .navigationTitle("Summary")
                .navigationBarBackButtonHidden(true)
            }
            .tabItem {
                Image(systemName: "list.dash")
                Text("Summary")
            }
        }
        .onAppear{
            self.isPresented = true
        }
        .fullScreenCover(isPresented: $isPresented, content: LoginView.init)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

and now it actually seems to work. Never have thought of fullScreenCover - thanks! :)

Upvotes: 0

Related Questions