SwiftUI - 如何将工具栏添加到 NavigationView 内的 TabView 选项卡?

Posted

技术标签:

【中文标题】SwiftUI - 如何将工具栏添加到 NavigationView 内的 TabView 选项卡?【英文标题】:SwiftUI - How to add toolbars to TabView tabs inside a NavigationView? 【发布时间】:2021-09-13 10:58:26 【问题描述】:

我正在尝试将不同的toolbars 添加到我的每个选项卡,但它们没有显示。该应用程序将主要在横向 iPad 上使用,我可以将工具栏添加到 TabView 本身并显示它们,但是我不知道如何将按钮按下导航堆栈传递给各个视图/视图模型本地处理。

我尝试添加新的NavigationViews(包括.stacknavigationViewStyles),但这仍然只是在视图中添加了另一列。

这是一些准系统,工作代码:

import SwiftUI

@main
struct NavTabTestApp: App 
    var body: some Scene 
        WindowGroup 
            ContentView()
        
    


struct ContentView: View 
    var body: some View 
            MasterView()
    


struct MasterView: View 
    var body: some View 
        NavigationView 
            List 
                ForEach(0..<20)  index in
                    NavigationLink(
                        destination: DetailView(index: index)
                            .navigationTitle("Row \(index)")
                    ) 
                        Text("\(index) th row")
                    .tag(index)
                
            .navigationTitle(Text("Ratty"))
        
    


struct DetailView: View 
    var index: Int
    
    @State var selectedTab = 1
    
    var body: some View 
        TabView(selection: $selectedTab) 
            Tab1(index: index).tabItem  Label("Tab1", systemImage: "list.dash") 
            Tab2(index: index).tabItem  Label("Tab2", systemImage: "aqi.medium") 
            Tab3(index: index).tabItem  Label("Tab3", systemImage: "move.3d") 
        
    


struct Tab1: View     
    var index: Int
    
    var body: some View 
        Text("This is \(index) in tab 1")
            .toolbar 
                ToolbarItem(placement: .primaryAction) 
                    Button("Bingo")  print("Bingo") 
                
            
    


struct Tab2: View 
    var index: Int
    
    var body: some View 
        Text("This is \(index) in tab 2")
            .toolbar 
                ToolbarItem(placement: .primaryAction) 
                    Button("Bongo")  print("Bongo") 
                
            
    


struct Tab3: View 
    var index: Int
    
    var body: some View 
        Text("This is \(index) in tab 3")
            .toolbar 
                ToolbarItem(placement: .primaryAction) 
                    Button("Banjo")  print("Banjo") 
                
            
    

我开始怀疑这是否可能,以及在每个选项卡顶部使用按钮实现我自己的视图是否会更好。

编辑:

【问题讨论】:

NavigationView 应该是 TabView 的子项,而不是您所做的其他方式。导航到 DetailsView 是否重要?您可以呈现它并为每个选项卡视图添加一个 NavgationView? @mahan - 我尝试将 NavigationView 移动到 List 中,但我的视图变得毫无意义。我不明白我可以把它放在哪里。另外,我没有绑定到 NavigationLink,但是当从列表中选择某些内容时,我将如何填充 Detail 视图? 【参考方案1】:

不确定这是否有帮助,但它确实通过导航视图中的工具栏回顾了一些有趣的概念。

链接:Stewart Lynch

【讨论】:

谢谢。有趣的东西,但我认为我的问题与 TabViews 处理/继承 NavigationViews 的特定方式有关。【参考方案2】:

您只需要使用一级NavigationView。换句话说,你不应该嵌套NavigationViews。看看这个答案。

Only Back Button Visible on Custom Navigation Bar SwiftUI


    NavgationView 用作您所使用的MasterView。 为每个Tab# 视图使用NavigationView。 在MasterViewDetailsView 之间切换。 在MasterView 中使用Button 而不是NavigationLink(您可以将其自定义为NavigationLink) 在每个Tab# 视图中使用自定义后退按钮。

这控制应该显示MasterViewDetailsView 中的哪一个。

class BaseViewModel: ObservableObject 
    @Published var userFlow: UserFlow = .masterView
    
    init()
        userFlow = .masterView
    
    
    enum UserFlow 
        case masterView, detailsView
    


此视图可用于ContentView 或代替它。当您在MasterView 中并单击列表行之一时,设置appState.userFlow = .detailView。单击后退按钮时,设置appState.userFlow = .masterView

这样做,您在两个视图之间切换,一次显示一个NavigationView

截至目前,它没有动画。如果您愿意,请使用

https://developer.apple.com/tutorials/swiftui/animating-views-and-transitions

struct BaseView: View 
    
    @EnvironmentObject var appState: BaseViewModel
    
    @State var index: Int = 0
    
    var body: some View 
        Group 
            switch appState.userFlow 
            case .masterView:
                MasterView(index: $index)
            default:
                DetailView(index: index)
            
        
        .edgesIgnoringSafeArea(.bottom)
    



完整代码

struct ContentView: View 
    var body: some View 
        BaseView().environmentObject(BaseViewModel())
    



class BaseViewModel: ObservableObject 
    @Published var userFlow: UserFlow = .masterView
    
    init()
        userFlow = .masterView
    
    
    enum UserFlow 
        case masterView, detailsView
    



struct BaseView: View 
    
    @EnvironmentObject var appState: BaseViewModel
    
    @State var index: Int = 0
    
    var body: some View 
        Group 
            switch appState.userFlow 
            case .masterView:
                MasterView(index: $index)
            default:
                DetailView(index: index)
            
        
        .edgesIgnoringSafeArea(.bottom)
    



struct MasterView: View 
    @EnvironmentObject var appState: BaseViewModel
    
    @Binding var index: Int
    
    var body: some View 
        NavigationView 
            List 
                ForEach(0..<20)  index in
                    Button(action: 
                        appState.userFlow = .detailsView
                        $index.wrappedValue = index
                    , label: 
                        HStack 
                            Text("\(index) th row")
                            Spacer()
                            Image(systemName: "greaterthan")
                        
                    )
                    .tag(index)
                
            .navigationTitle(Text("Ratty"))
        
    


struct DetailView: View 
    var index: Int
    
    @State var selectedTab = 1
    
    var body: some View 
        TabView(selection: $selectedTab) 
            Tab1(index: index).tabItem  Label("Tab1", systemImage: "list.dash") 
            Tab2(index: index).tabItem  Label("Tab2", systemImage: "aqi.medium") 
            Tab3(index: index).tabItem  Label("Tab3", systemImage: "move.3d") 
        
    


struct Tab1: View 
    @EnvironmentObject var appState: BaseViewModel
    
    var index: Int
    
    var body: some View 
        NavigationView 
            Text("This is \(index) in tab 1")
                .toolbar 
                    ToolbarItem(placement: .navigationBarLeading) 
                        Button("back")  appState.userFlow = .masterView  
                    
                    ToolbarItem(placement: .navigationBarTrailing) 
                        Button("Bingo")  print("Bingo") 
                    
                
        
    


struct Tab2: View 
    @EnvironmentObject var appState: BaseViewModel
    
    var index: Int
    
    var body: some View 
        NavigationView 
            Text("This is \(index) in tab 2")
                .toolbar 
                    ToolbarItem(placement: .navigationBarLeading) 
                        Button("back")  appState.userFlow = .masterView  
                    
                    ToolbarItem(placement: .primaryAction) 
                        Button("Bongo")  print("Bongo") 
                    
                
        
    


struct Tab3: View 
    @EnvironmentObject var appState: BaseViewModel
    var index: Int
    
    var body: some View 
        NavigationView 
            Text("This is \(index) in tab 3")
                .toolbar 
                    ToolbarItem(placement: .navigationBarLeading) 
                        Button("back")  appState.userFlow = .masterView  
                    
                    ToolbarItem(placement: .primaryAction) 
                        Button("Banjo")  print("Banjo") 
                    
                
        
    



我已经自定义了xtwistedx 的solution。

【讨论】:

谢谢!这看起来很有希望,我明天会完成它。但是,不同的工具栏出现在主(列表)视图中,而不是单个详细信息/选项卡视图中。我会看看我是否可以使用你的代码来实现这一点,然后我会相信你的回答。 不,工具栏已附加到选项卡视图。 @Magnas 是的,工具栏附加到代码中的选项卡视图,但工具栏附加到主(左)视图,我希望不同的工具栏附加到细节(右)意见。请查看我对问题的编辑。 @Magnas 选项卡视图是否有导航项(标题、按钮等)?

以上是关于SwiftUI - 如何将工具栏添加到 NavigationView 内的 TabView 选项卡?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 SwiftUI 向 macOS 应用程序添加工具栏?

如何在 SwiftUI 中清除列表项上的默认突出显示灰色?

如何将 SwiftUI 视图动态添加到父视图?

如何将字典项分别添加到 SwiftUI 列表中

如何使用 SwiftUI 将上下文菜单添加到 NavigationLink?

如何将我的自定义 ButtonStyle 添加到 swiftui3 中的快捷方式 swiftui .buttonstyle() 属性