当使用SwiftUI中的TabView时,NavigationView标题不会出现

15

我有两个视图,它们各自包含一个带标题的NavigationView。我创建了一个TabBar View,它也有一个NavigationView。

struct TabbarView: View {
var body: some View {
    NavigationView{
    TabView {
        MainContentView()
            .tabItem {
                VStack {
                    Text("Main")
                }
        }.tag(0)

        SearchContentView()
            .tabItem {
                VStack {
                    Text("Search")
                }
        }.tag(1)
    }
    }.navigationBarBackButtonHidden(true)
    .navigationBarHidden(true)
}

我已尝试隐藏此视图的navigationBar,但无效。只有此视图的navigationBar出现。

这是MainContentView()

struct MainContentView: View {

var body: some View {
    NavigationView {
        Text("Some Content View")
        }
    .navigationBarTitle("Travel")
}

有什么想法如何着手处理这个问题。谢谢!

更新: 基本上,当我点击一个登录按钮时,我通过NavigationLink传递TabBarView()。

   NavigationLink(destination: TabbarView()) {
                        HStack {
                            Text("Log In")
                        }
                        .padding()
                        .frame(width: geometry.size.width - 40, height: 40)
                        .foregroundColor(Color.white)
                        .background(Color.blue)
                        .cornerRadius(5)
                }.padding(.bottom, 40)

在执行此操作时,它显示了具有子视图的TabbarView(),这是我看到的内容:

"Travel"上方的空间(childView的navigationBarTitle)是tabbar的navigationBar,因为我将其推入了navigationStack。

enter image description here

4个回答

17
首先需要强调的是,您代码中的所有导航栏修改器都应该是在 NavigationView 中的视图上的修饰符,而不是在 NavigationView 自身上的修饰符。例如来自 .navigationBarTitle 的文档:

仅当此视图在 NavigationView 中且可见时,此修改器才会生效。

另外,没有必要在您的 TabView 外层再套一个 NavigationView,然后再在 MainContentView 内部套一个。这只会导致嵌套的导航栏,而这肯定不是您想要的。相反,只需使用一个 NavigationView 即可。我还建议您不要将 NavigationView 放在 MainContentView 的主体内。

我已经重构了您的代码以展示我的意思,尽管我不确定您试图使用 .navigationBarBackButtonHidden.navigationBarHidden 的位置,所以我省略了它们。请记住,它们的功能与 .navigationBarTitle 相同 - 您需要将它们用作 NavigationView 中的视图上的修饰符,而不是在 NavigationView 自身上的修饰符。

struct TabBarView: View {
    var body: some View {
        TabView {
            NavigationView {
                MainContentView()
            }
                .tag(0)
                .tabItem {
                    Text("Main")
                }

            SearchContentView()
                .tag(1)
                .tabItem {
                    Text("Search")
                }
        }
    }
}
struct MainContentView: View {
    var body: some View {
        Text("Some Content View")
            .navigationBarTitle("Travel")
    }
}

你可能会注意到,我还从.tabItem中删除了VStack。你可以将TextImage都放在.tabItem中,无需使用VStack,如果我没有误解的话,.tabItem会忽略除TextImage以外的任何内容。


感谢您的答案。如果有人希望导航栏像正常情况下一样伸展到顶部安全区以下,那么需要在 TabView 本身上添加 edgesIgnoringSafeArea(.top) - tomcully
如果我将NavigationView嵌套在TabView中,我会在我导航视图上推送的每个子视图上看到TabView底部栏。有没有办法隐藏它? - ILuvProgramming
这不是一个好的答案,因为您无法在子视图中隐藏选项卡视图... 这样就失去了目的。 - Andre
1
@Andre 隐藏子视图中的选项卡栏与此问题无关。此外,隐藏选项卡栏是使用hidesBottomBarWhenPushed完成的,据我所知,目前在SwiftUI中不可用。将TabView嵌套在NavigationView中并不是允许隐藏选项卡栏的方法。 - graycampbell
@graycampbell 我现在才知道这个事实。看起来文档并不是太好。谢谢你的澄清! - Andre
显示剩余5条评论

2
如果您需要在选项卡视图之前添加登录/注册视图,请不要使用NavigationView来包装它。在登录/注册视图中,保留HTML标签即可。
@EnvironmentObject var authService:AuthService

var body: some View{
    ZStack{
        if(!authService.isSignedIn){
            Button(action: {
                self.authService.signIn()
            }) {
                Text("Login")
            }
        }
        else{
            TabBarView()
        }
    }
}

在子视图中,您可以使用@EnvironmentObject控制isSignedIn变量,并在注销时更改该值。以下是TabBarView()的示例用法:
var body: some View {
    TabView {
        NavigationView{
            FirstView()
        }
        .tabItem {
            VStack{
                Image("first")
                Text("First")
            }
        }
        NavigationView{
            SecondView()
        }
        .tabItem {
            VStack{
                Image("second")
                Text("Second")
            }
        }
    }
}

这可能是选项卡视图之一:
@EnvironmentObject var authService:AuthService

var body: some View {
    TextView("Hello World")
    .navigationBarItems(trailing: LogOutButton(logOutFunction: authService.signOut))
}

这样做没问题,但是当authService.isSignedIn为true时,你不会得到动画效果。它只会闪烁到TabView中。不够可爱。 - Ryuuzaki Julio
有没有更好的方法从登录页面导航到选项卡视图? - Lina_F

0

在iOS 13中也适用:

var body: some View {
        TabView {
            NavigationView {
                FirstTabbarView(viewModel: viewModel)
                    .navigationBarTitle("NavBar title Tabbar1", displayMode: .inline)
            }
            .tabItem {
                Image(systemName: "house.fill")
                Text("Tab bar 1")
            }
            
            NavigationView {
                SecondTabbarView(viewModel: viewModel)
                    .navigationBarTitle("Navbar title Tabbar 2", displayMode: .inline)
            }
            .tabItem {
                Image(systemName: "person.fill")
                Text("Tab bar 2")
            }
            
        }
    }

0
如果你想要动态导航标题,你可以这样做
struct ContentView: App {
@State var selection = 1

var body: some Scene {
    WindowGroup {
        NavigationView {
            TabView(selection: $selection) {
                GridView()
                    .tabItem {
                        Label("Study", systemImage: "book")
                            .symbolRenderingMode(.hierarchical)
                    }
                    .tag(1)
                
                StudyView()
                    .tabItem {
                        Label("Test", systemImage: "graduationcap")
                    }
                    .tag(2)
            }
            .navigationTitle(selection == 1 ? "Study a Language" : "Take a Test")
        }
    }
}

如果你收到这样的警告信息Trying to pop to a missing destination - SwiftUI/NavigationBridge_PhoneTV.swift:213,你可以参考这篇博客https://computerlounge.it/swifui-trying-to-pop-to-missing-destination/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接