代码之家  ›  专栏  ›  技术社区  ›  Tulon

从子导航视图中取消选项卡视图SwiftUI

  •  0
  • Tulon  · 技术社区  · 5 年前

    我的导航流程:

    enter image description here

    给,我的 View A View G 位于一个导航视图下。

    NavigationView {
        ViewA()
    }
    

    以及来自 View D & 视图G 我要搬到我的 TabView H 通过模态,如下所示:

    Button(action: {
        isPresented.toggle()
    }, label: {
       Text("GO!")
    })
    .fullScreenCover(isPresented: $isPresented) {
        TabbarView()
    }
    

    在我的选项卡视图中,所有视图都有自己的导航视图,如下所示:

    TabView(selection: $tabbarViewModel.tabSelection) {
        NavigationView {
            HomeView()
                .navigationBarTitleDisplayMode(.inline)
                .toolbar {
                    ToolbarItem(placement: .principal) {
                        Text("Home")
                    }
                }
        }.navigationViewStyle(StackNavigationViewStyle())
            .tabItem {
                Image(systemName: "house")
                    .renderingMode(.template)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                Text("Home")
            }
            .tag(0)
    
        NavigationView {
            CartView()
                .navigationBarTitleDisplayMode(.inline)
                .toolbar {
                    ToolbarItem(placement: .principal) {
                        Text("Cart")
                    }
                }
        }.navigationViewStyle(StackNavigationViewStyle())
            .tabItem {
                Image(systemName: "cart")
                    .renderingMode(.template)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                Text("Cart")
            }
            .tag(1)
    
        NavigationView {
            ProductView()
                .navigationBarTitleDisplayMode(.inline)
                .toolbar {
                    ToolbarItem(placement: .principal) {
                        Text("Product")
                    }
                }
        }.navigationViewStyle(StackNavigationViewStyle())
            .tabItem {
                Image(systemName: "seal")
                    .renderingMode(.template)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                Text("Product")
            }
            .tag(2)
    
        NavigationView {
            ProfileView()
                .navigationBarTitleDisplayMode(.inline)
                .toolbar {
                    ToolbarItem(placement: .principal) {
                        Text("Profile")
                    }
                }
        }.navigationViewStyle(StackNavigationViewStyle())
            .tabItem {
                Image(systemName: "person")
                    .renderingMode(.template)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                Text("Profile")
            }
            .tag(3)
    }
    .accentColor(Color("AppsDefaultColor"))
    

    现在我想回到 viewA ,说来自 Home View 通过按下 Sign Out 按钮我试过这个,只是想看看它是否能让我回到以前的视图,但它不起作用。

    struct HomeView: View {
        @Environment(\.presentationMode) var presentationMode
        
        var body: some View {
            Button(action: {
                self.presentationMode.wrappedValue.dismiss()
            }, label: {
                Text("Dismiss")
            })
        }
    }
    

    那么,我该如何取消tabview并返回到我的 Root view A ?

    0 回复  |  直到 5 年前
        1
  •  0
  •   Tulon    5 年前

    我终于做到了。为了回滚到“根”视图,我使用了以下方法:

    NavigationLink(destination: <#T##_#>, tag: <#T##Hashable#>, selection: <#T##Binding<Hashable?>#>, label: <#T##() -> _#>)
    

    为了否定现有观点,我使用了以下内容:

    UIApplication.shared.windows.first?.rootViewController?.dismiss(animated: true, completion: nil)
    

    老实说,这很简单。 我们需要做的一切 NavigationLink selection 在这种情况下,它被选择为Item nil & dismiss 整个项目的模态。 所有这些都是在选项卡栏视图模型类内部完成的,并借助于 @EnvironmentObject

    首先创建 TabbarViewModel: ObservableObject :

    import Foundation
    import SwiftUI
    
    class TabbarViewModel: ObservableObject {
        @Published var tabSelection: Int = 0
        @Published var selectedItem: String? = nil
        
        func gotoRootView() {
            withAnimation {
                UIApplication.shared.windows.first?.rootViewController?.dismiss(animated: true, completion: nil)
                selectedItem = nil
            }
        }
    }
    

    现在,让我们创建 ViewA 哪个是 AuthListView :

    import SwiftUI
    
    struct CellItem: Identifiable {
        var id = UUID()
        let title: String
        let image: String
        let destination: AnyView
    }
    
    struct AuthListView: View {
        var body: some View {
            AuthListContentView()
                .navigationBarHidden(true)
        }
    }
    
    struct AuthListContentView: View {
        @State private var cellList: [CellItem] = [
            CellItem(title: "Icon", image: "", destination: AnyView(EmptyView())),
            CellItem(title: "Phone", image: "Phone", destination: AnyView(PhoneView())),
            CellItem(title: "Email", image: "Email", destination: AnyView(SignInView())),
            CellItem(title: "Google", image: "Google", destination: AnyView(GoogleView())),
            CellItem(title: "Facebook", image: "Facebook", destination: AnyView(FacebookView())),
            CellItem(title: "Twitter", image: "Twitter", destination: AnyView(TwitterView()))]
        
        var body: some View {
            List(cellList, id: \.id) { item in
                if item.title == "Icon" {
                    IconImageView()
                } else {
                    AuthListCell(cellItem: item)
                }
            }
        }
    }
    
    struct IconImageView: View {
        var body: some View {
            VStack {
                Image("firebase")
                    .renderingMode(.original)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 120, height: 120, alignment: .center)
            }
            .frame(maxWidth: .infinity, minHeight: 120, alignment: .center)
            .padding(.top, 50)
            .padding(.bottom, 50)
        }
    }
    

    这是auth-View的每个单元格:

    import SwiftUI
    
    struct AuthListCell: View {
        var cellItem: CellItem
        @EnvironmentObject var tabbarViewModel: TabbarViewModel
        
        var body: some View {
            
            NavigationLink(
                destination: cellItem.destination,
                tag: cellItem.title,
                selection: $tabbarViewModel.selectedItem) {
                cell(cellItem: cellItem)
            }
        }
    }
    
    struct cell: View {
        var cellItem: CellItem
        var body: some View {
            HStack(spacing: 15) {
                Image(cellItem.image)
                    .renderingMode(.original)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(maxWidth: 28, maxHeight: .infinity, alignment: .center)
    
                Text(cellItem.title)
                    .foregroundColor(Color("DefaultText"))
                    .font(.system(size: 17))
                Spacer()
            }
            .padding(.top, 5)
            .padding(.bottom, 5)
        }
    }
    

    将此视图加载到您的 ContentView 在导航视图下:

    struct ContentView: View {
        @Environment(\.managedObjectContext) private var viewContext
    
        var body: some View {
            NavigationView {
                AuthListView()
            }
            .navigationViewStyle(StackNavigationViewStyle())
        }
    }
    

    到目前为止,我们可以推动 ViewB 从…起 视图A 。在这里,我只显示的导航流程 视图A 推送> 视图B 推送> ViewC 现在> TabView >然后解散 选项卡视图 从…起 HomeView 然后回到根 视图A ,因为其他视图也将遵循相同的观点。它也可以从任何选项卡栏视图的子导航中工作。所以让我们创造 视图B ( PhoneView )并推动 ViewC ( PINView ):

    视图B:

    struct PhoneView: View {
        var body: some View {
            PhoneContentView()
                .navigationBarTitle("Phone Number", displayMode: .inline)
        }
    }
    
    struct PhoneContentView: View {
        var body: some View {
            NavigationLink(destination: PINView()) {
                Text("Go")
            }
        }
    }
    

    视图C:

    struct PINView: View {
        var body: some View {
            PINContentView()
                .navigationBarTitle("PIN", displayMode: .inline)
        }
    }
    
    struct PINContentView: View {
        @State private var isPresented = false
        
        var body: some View {
            Button(action: {
                isPresented.toggle()
            }, label: {
                Text("Sign In")
            })
            .fullScreenCover(isPresented: $isPresented) {
                TabbarView()
            }
        }
    }
    

    到目前为止,我们已经展示了以前的选项卡视图 ViewC 。这是我们的选项卡视图:

    import SwiftUI
    
    struct TabbarView: View {
        @EnvironmentObject var tabbarViewModel: TabbarViewModel
    
        var body: some View {
            TabView(selection: $tabbarViewModel.tabSelection) {
                NavigationView {
                    HomeView().navigationBarTitle("Home", displayMode: .inline)
                }
                .navigationViewStyle(StackNavigationViewStyle())
                .tabItem {
                    Image(systemName: "house")
                        .renderingMode(.template)
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                    Text("Home")
                }
                .tag(0)
    
                NavigationView {
                    CartView().navigationBarTitle("Cart", displayMode: .inline)
                }
                .navigationViewStyle(StackNavigationViewStyle())
                .tabItem {
                    Image(systemName: "cart")
                        .renderingMode(.template)
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                    Text("Cart")
                }
                .tag(1)
    
                NavigationView {
                    ProductView().navigationBarTitle("Product", displayMode: .inline)
                }
                .navigationViewStyle(StackNavigationViewStyle())
                .tabItem {
                    Image("product")
                        .renderingMode(.template)
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                    Text("Product")
                }
                .tag(2)
                
                NavigationView {
                    ProfileView().navigationBarTitle("Profile", displayMode: .inline)
                }
                .navigationViewStyle(StackNavigationViewStyle())
                .tabItem {
                    Image(systemName: "person")
                        .renderingMode(.template)
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                    Text("Profile")
                }
                .tag(3)
            }
            .accentColor(Color("AppsDefaultColor"))
        }
    }
    

    现在,如果我想取消呈现的选项卡视图&按返回到根目录视图 sign out 我的按钮 主页视图 ,我所要做的就是打电话 tabbarViewModel.gotoRootView() 这样地:

    struct HomeView: View {
        @EnvironmentObject var tabbarViewModel: TabbarViewModel
        
        var body: some View {
            Button(action: {
                tabbarViewModel.gotoRootView()
            }, label: {
                Text("Sign Out")
            })
        }
    }
    

    我可以取消选项卡视图,也可以从HomeView的子视图转到根视图。让我们从主视图转到子视图:

    struct HomeView: View {
        
        var body: some View {
            NavigationLink(destination: HomeDetailsView()) {
                Text("Go")
            }
        }
    }
    

    这是HomedetailsView`,通过执行相同的调用,我可以实现如下相同的结果:

    struct HomeDetailsView: View {
        var body: some View {
            HomeDetailsContentView()
            .navigationBarTitle("Home Details", displayMode: .inline)
        }
    }
    
    struct HomeDetailsContentView: View {
        @EnvironmentObject var tabbarViewModel: TabbarViewModel
        
        var body: some View {
            Button(action: {
                tabbarViewModel.gotoRootView()
            }, label: {
                Text("Dismiss")
            })
        }
    }
    

    通过此操作,您可以取消选项卡视图,并从项目的任何视图转到根视图。:)

    推荐文章